본문 바로가기

Programming/Manim Lectures

[06-1-E] Animation : Transformation series (1/3)

반응형

When there are two objects A and B, we will learn about the animation effect that A gradually changes to B.

Class Parameters Explanation
MoveAlongPath mobject,
target_mobject=None
mobject is converted to the location/form of target_mobject.
At this time, the name of the object that has changed and remains is mobject not target_mobject.
ClockwiseTransform mobject,
target_mobject=None
mobject is converted to the position/shape of target_mobject.
When mobject moves to target_mobject, it is converted while flying clockwise.
At this time, the name of the object that has changed and remained is mobject.
CounterclockwiseTransform mobject,
target_mobject=None
mobject is converted to the position/shape of target_mobject.
When mobject moves to target_mobject, it is converted while flying counterclockwise.
At this time, the name of the object that has changed and remains is mobject.
ReplacementTransform mobject,
target_mobject=None
mobject is converted to the location/form of target_mobject.
At this time, the name of the object that has changed and remains is target_mobject.
Swap *mobjects Two objects swapped each other
TransformFromCopy mobject,
target_mobject=None
As mobject moves toward target_mobject, the shape/color changes, but the original mobject remains
CyclicReplace *mobjects Move the given mobjects one by one.
The first one changes to the second, the second to the third, the last one to the first, and so on, as if on a circular cycle.
ScaleInPlace mobject,
scale_factor
Animation effect that changes mobject to the size of scale_factor
FadeToColor mobject, color Animation effect that turns mobject into the given color
Restore mobjects Animation that returns mobject to the state it was in when mobject.save_state() was called.
MoveToTarget mobjects Animation to move mobject to mboject.target

Transform class

object > Animation > Transform
manimlib.animation.transform.Transform(self, mobject, target_mobject=None, **kwargs)

A mobject is converted to the location/form of target_mobject.

At this time, the last remaining object name is mobject.

self.play(Transform(square, circle), run_time=3)
   CONFIG = {
        "path_arc": 0,
        "path_arc_axis": OUT,
        "path_func": None,
        "replace_mobject_with_target_in_scene": False,
    }
Parameters: mobject
    Object to be animated

Parameters: target_mobject=None
    Target object to be converted. 
    The object moves to the location of target_mobject and changes to the shape of target_mobject.

Parameters: **kwargs
    CONFIG values of Transform and Animation

    Frequently used variables are, 
    - run_time=1.0: Animation running time
    - rate_func=smooth: Velocity change function when the animation is running
    

The Transform class shows an animation effect that gradually changes the position/shape of the object targeting mobject.

When the rectangle A is on the left and the circle B is on the right, the effect is that the rectangle gradually turns into a circle as it flies to the circle.

self.play(Transform(square, circle), run_time=3)

You can see the changing process in the snapshot below.

 

Note that what is the name of the object that turned into a circle left at the end, which is variable A. It is convenient to understand that A has changed to the form of B.

 

The reason why the remaining variable is important is because, after performing the Transform once, what kind of object variable should be used when re-animating the transformed object?

Since we transformed A into B, A remains, and we can use some animation for this A again.

The sorce code and output video for the above exampel is as follows.

 

class TransformTest(Scene):
    def construct(self):
        self.transform_to_target()
        # self.cyclic()

    def get_text(self, str):
        return Text(str, size=0.5, color=YELLOW, stroke_width=0)

    def transform_to_target(self):
        self.left_name = self.get_text("A").shift(UP * 2 + LEFT * 3)
        self.right_name = self.get_text("B").shift(UP * 2 + RIGHT * 3)

        self.square = Square().shift(LEFT*3)
        self.circle = Circle(fill_opacity=1, color=RED).shift(RIGHT*3)

        self.objs = VGroup(self.left_name, self.right_name, self.square, self.circle)
        self.objs.save_state()

        t_classes = {
            "1. Transform": Transform,
            "2. ClockwiseTransform": ClockwiseTransform,
            "3. CounterclockwiseTransform": CounterclockwiseTransform,
        }

        for name, cla in t_classes.items():
            self.transform(name, cla)

        self.replacement_transform("4. ReplacementTransform", ReplacementTransform)
        self.transform_from_copy("5. TransformFromCopy", TransformFromCopy)
        self.do_swap("6. Swap", Swap)

    def transform(self, name, ani_class):
        ani_name = self.get_text(name).to_corner(UL)
        self.add(ani_name, self.objs)
        self.wait()

        self.play(
            ani_class(self.square, self.circle, run_time=3),
            FadeOut(self.right_name),
            self.left_name.move_to, self.right_name, run_time=3,
        )
        self.wait()
        self.remove(ani_name, self.objs)
        self.objs.restore()


    def replacement_transform(self, name, ani_class):
        ani_name = self.get_text(name).to_corner(UL)
        self.add(ani_name, self.objs)
        self.play(
            ani_class(self.square, self.circle, run_time=2),
            FadeOut(self.left_name),
        )
        self.wait()
        self.remove(ani_name, self.objs)
        self.objs.restore()

    def transform_from_copy(self, name, ani_class):
        ani_name = self.get_text(name).to_corner(UL)
        self.add(ani_name, self.objs)
        self.play(
            ani_class(self.square, self.circle, run_time=2),
        )
        self.wait()
        self.remove(ani_name, self.objs)
        self.objs.restore()

    def do_swap(self, name, ani_class):
        ani_name = self.get_text(name).to_corner(UL)
        self.add(ani_name, self.objs)
        self.play(
            ani_class(self.square, self.circle, run_time=2),
            self.left_name.shift, RIGHT*6,
            self.right_name.shift, LEFT * 6,
        )
        self.wait()
        self.remove(ani_name, self.objs)
        self.objs.restore()

 

 


Classification for Transform, ReplaceTransform, TransformFromCopy

Before we dive into other classes related to transforms. let's look at the differences between the Transform, ReplaceTransform, and TransformFromCopy classes.

 

These three classes are most commonly used transform effects, but their behavior is subtly different, which is a bit confusing. Let's point out what's different.

 

If you understand the code below, you will definitely see the difference.

 

 

We will create an animation in which three objects are arranged side by side, such as a triangle, a square, and a circle, while only the triangle is displayed on the screen, the triangle turns into a rectangle and the rectangle turns into a circle.

 

If the triangle is called A, the square is B, and the circle is C, using the Transform class,

 

  Transform(A,B)
  Transform(A,C)

 

If we use ReplacementTransform,

  ReplacementTransform(A,B)
  ReplacementTransform(B,C)

 

If we use TransformFromCopy,

  TransformFromCopy를(A,B)
  TransformFromCopy를(B,C)

 

 

Let's explain.

 

In the case of Transform, A is changed to B, and then A is left in place of B.

At this time, the shape of A is changed to B's shape of rectangle. 

In that state, the rectangle should be changed to the circle, so you have to do Transform(A,C)

 

In the case of ReplacementTransform, B is replaced by A after A is changed to B. In other words, after A is changed to B, what remains is an object with the name B

So, if you want to change the rectangle to circle, do TransformReplacement(B,C), and after doing this, the last thing left is a circle with the name of C.

 

In the case of TransformFromCopy, you can think that it's similiar to ReplacementTransform except the starting object is remained. That is, when the shape changes from A to B with TransformFromCopy, A remains, and the cloned A object flies to B to become the sahpe of B, and the name becomes B.

Subsequently, B changes to C, B stays, and cloned B flies to C, and turns into C, then becoms the name of C.

 

The explanation is a bit complicated, but if you look at the picture below you can understand it.

 


Below is the source code that created as described above.

class DifferenceOfTransform(Scene):
    def construct(self):
        self.tri = Triangle().to_edge(LEFT, buff=0.5)
        self.square = Square()
        self.circle = Circle().to_edge(RIGHT, buff=0.5)

        self.group = VGroup(self.tri, self.square, self.circle)
        self.group.save_state()

        self.transform("Transform(A,B)", "Transform(A,C)")
        self.replacement_transform("ReplacementTransform(A,B)", "ReplacementTransform(B,C)")
        self.transform_from_copy("TransformFromCopy(A,B)", "TransformFromCopy(B,C)")

    def transform(self, s1, s2):
        text = VGroup(
            Text(s1, stroke_width=0, color=YELLOW, size=0.4),
            Text(s2, stroke_width=0, color=YELLOW, size=0.4),
        ).arrange(DOWN, aligned_edge=LEFT)
        self.add(text.to_edge(UP, buff=1))

        self.group.restore()
        self.add(self.tri)

        self.play(Transform(self.tri, self.square), run_time=3)
        self.play(Transform(self.tri, self.circle), run_time=3)
        self.wait()

        self.remove(text, self.tri, self.square, self.circle)

    def replacement_transform(self, s1, s2):
        text = VGroup(
            Text(s1, stroke_width=0, color=YELLOW, size=0.4),
            Text(s2, stroke_width=0, color=YELLOW, size=0.4),
        ).arrange(DOWN, aligned_edge=LEFT)
        self.add(text.to_edge(UP, buff=1))

        self.group.restore()

        self.play(ReplacementTransform(self.tri, self.square), run_time=3)
        self.play(ReplacementTransform(self.square, self.circle), run_time=3)
        self.wait()

        self.remove(text, self.tri, self.square, self.circle)

    def transform_from_copy(self, s1, s2):
        text = VGroup(
            Text(s1, stroke_width=0, color=YELLOW, size=0.4),
            Text(s2, stroke_width=0, color=YELLOW, size=0.4),
        ).arrange(DOWN, aligned_edge=LEFT)
        self.add(text.to_edge(UP, buff=1))

        self.group.restore()
        self.add(self.tri)

        self.play(TransformFromCopy(self.tri, self.square), run_time=3)
        self.play(TransformFromCopy(self.square, self.circle), run_time=3)
        self.wait()

 


Next: [06-1-F] Animation : Transformation series (2/3)

 

[06-1-F] Animation : Transformation series (2/3)

CyclicReplace class object > Animation > Transform > CyclicReplace manimlib.animation.transform.CyclicReplace(self, *mobjects, **kwargs) Move the given mobjects one by one. The first one changes t..

infograph.tistory.com

Go To: [99] Table of Contents

반응형