본문 바로가기

Programming/Manim Lectures

[06-3-C] Use Updating Class

반응형

In the previous page, we looked at an animation technique that updates objects every frame using add_updater or always_redraw.

 

These methods,

  • Create some update_func that transforms tgt_mob.
  • Regist update_func in the list of updaters functions of tgt_mob object.
    --> 'tgt_mob.add_updater(update_func)' or 'tgt_mob = always_redraw(update_func)'
  • Play base_mob or ValueTracker, which will be base object, animation of tgt_mob is generated.
    --> 'self.play(move_func_for_base_mob)' or 'self.play(tracker.set_value, target_value)'

The above method uses add_updater or always_redraw at the front of play to change the list of updaters. In addition to this method, we can specify an update function in the 'play' method. The classes used in this way are UpdateFromFunc and UpdateFromAlphaFunc.

 


UpdateFromFunc class

object > Animation > UpdateFromFunc
manimlib.animation.update.UpdateFromFunc(self, mobject, update_function, **kwargs)

The mobject given as a parameter is updated using the update_function and animated.

 

Parameters: mobject
    Target object

Parameters: update_function
    Function that changes mobject's state(position, color, etc)     

When a dot moves, we will use UpdateFromFunc to create an animation that follows the label text along this dot.

 

    def update_from_func(self):
        dot = Dot().to_edge(LEFT)
        label = TextMobject("Hello").next_to(dot,UP)

        def update_func(mob):
            mob.next_to(dot,UP)

        self.play(
            dot.to_edge,RIGHT,
            UpdateFromFunc(label, update_func),
            run_time=5,
        )

Note that when we create an update function, we use the target object as a parameter and the variable values of some other object (dot here) within the update function.

        def update_func(mob):
            mob.next_to(dot,UP)

 

In the play method, while moving the dot, use UpdateFromFunc at the same time, so that the label moves according to the dot.

Note that the target object label and the update function update_func are used in the parameters of UpdateFromFunc.

        self.play(
            dot.to_edge,RIGHT,
            UpdateFromFunc(label, update_func),
            run_time=5,
        )

 

In the example above, it may be simpler if you do not use update_func and UpdateFromFunc, but group the label and dot into a VGroup, and then move the bound object together.

 

But, what if the label value changes as the dot moves? It's impossible by the way of grouping the dot and label together. You will probably need to use update_func and UpdateFromFunc as above.

 

Below is an example that shows the x-coordinate of dot instead of fixing the content of label as 'Hello'.

Only the contents of the update_func function have changed.

    def update_from_func2(self):
        dot = Dot().to_edge(LEFT)
        label = TextMobject("Hello").next_to(dot,UP)

        def update_func(mob):
            mob.next_to(dot, UP)

            x = dot.get_center()[0]
            new_label = TextMobject(str(round(x,0))).move_to(mob)

            mob.become(new_label)

        self.play(
            dot.to_edge,RIGHT,
            UpdateFromFunc(label, update_func),
            run_time=5,
        )

 

Image capture of the video

 


UpdateFromAlphaFunc class

 object > Animation > UpdateFromFunc > UpdateFromAlphaFunc
manimlib.animation.update.UpdateFromAlphaFunc(self, mobject, update_function, **kwargs)

We can write an update function using alpha values that vary from 0 to 1 during the animation. The UpdateFromAlphaFunc class is used for this.

 

Mobject is updated by update_function.

The update_function changes the mobject using the alpha value.

 

Parameters: mobject
    Target object

Parameters: update_function
    This function changes the state of mobject (position, color, etc.).
    Since alpha exists as a parameter, the state of mobject changes 
    according to this alpha value

The alpha value of a certain object mob is a value expressed as a value from 0 to 1 when the mob is animated.

When rate_func=linear, the change interval from 0 to 1 is constant over time, otherwise, the change interval varies according to the variable speed of rate_func.

 

In the example below, when the dot moves from left to right, the alpha value is displayed using UpdateFromAlphaFunc class.

 

Coding strategy is,

  • Create Dot and DecimalNumber, and place DecimalNumber on the top of the Dot
  • Create update function update_number(mob, alpha) for DecimalNumber.
  • In play, move the Dot from left to right and perform UpdateFromAlphaFunc(decimal, update_number)
  • When playing, test by changing rate_func to linear, smooth, there_and_back
    def watch_alpha_value(self):
        dot = Dot(radius=0.5, color=RED).to_edge(LEFT)
        dot.save_state()
        decimal = DecimalNumber(0).next_to(dot,UP)

        def update_number(mob, alpha):
            mob.set_value(alpha).next_to(dot, UP)

        self.add(dot, decimal)

        self.play(dot.to_edge, RIGHT,
            UpdateFromAlphaFunc(decimal, update_number),
            rate_func=linear,
            run_time=3,
        )

        dot.restore()
        self.play(dot.to_edge, RIGHT,
                  UpdateFromAlphaFunc(decimal, update_number),
                  rate_func=smooth,
                  run_time=3,
        )

        dot.restore()
        self.play(dot.to_edge, RIGHT,
                  UpdateFromAlphaFunc(decimal, update_number),
                  rate_func=there_and_back,
                  run_time=5,
        )

        self.wait()

 

 


If you see the UpdateFromAlphaFunc class used in play, only the target object decimal and the update function name update_number are used, such as UpdateFromAlphaFunc(decimal, update_number), and alpha is not passed anywhere.

 

But if you look at the update_number function it has alpha.

 

This is because the UpdateFromAlphaFunc class uses alpha in the update_number function because it is appended with alpha when it calls the update_number function internally.

class UpdateFromAlphaFunc(UpdateFromFunc):
    def interpolate_mobject(self, alpha):
        self.update_function(self.mobject, alpha)

Let's develop the above example, in which the alpha value changes as the point moves, so let's create an animation that gradually changes the color inside the point from red to yellow.

 

When there are two colors c1 and c2, the color between c1 and c2 according to the alpha value can be obtained by the interpolate_color method.

manimlib.utils.colors.interpolate_color(color1, color2, alpha)

 

In order to change the color while playing, you can play by specifying another updateFromAlphaFunc, the target object dot, and the function update_dot_color that changes the color.

UpdateFromAlphaFunc(dot, update_dot_color)

 

The full source code is below.

def update_color_alpha(self):
    dot = Dot(radius=0.5, color=RED).to_edge(LEFT)
    decimal = DecimalNumber(0).next_to(dot,UP)

    def update_number(mob, alpha):
        mob.set_value(alpha).next_to(dot, UP)

    def update_dot_color(mob, alpha):
        mob.set_color(interpolate_color(RED, YELLOW, alpha))

    self.add(dot, decimal)

    self.play(
        dot.to_edge, RIGHT,
        UpdateFromAlphaFunc(decimal, update_number),
        UpdateFromAlphaFunc(dot, update_dot_color),
        run_time=3,
    )

 

 

Output video is, 

 


 

Go To: [99] Table of Contents

 

반응형

'Programming > Manim Lectures' 카테고리의 다른 글

[99] Table of Contents  (0) 2020.06.09
[06-3-B] Use always_redraw  (0) 2020.06.09
[06-3-A] Use add_updater  (0) 2020.06.09
[06-3] Animation by Object Updating  (0) 2020.06.09
[06-2] Animation by Object's Method  (0) 2020.06.09