maciejwww
maciejwww

Reputation: 1196

How to animate object color changing with Manim?

I want to animate Dot object to periodically change its color.
Something like this:
dot

I've only found AnimatedBoundary class but it changes only the object's boundary (as the name says ofc).

Is there any way to achieve that with already existing tools?

Upvotes: 4

Views: 3112

Answers (2)

xax
xax

Reputation: 2120

Colored Dot

This is an approximation/improvement upon @NickGreefpool's answer above, to more closely resemble the question's source animation.

The inner label is added to better see where the Circle is on the path.

class ColoredDot(Scene):
    def construct(self):

        tracker = ValueTracker(0)

        def update_color(obj):
            T = tracker.get_value()
            rgbcolor = [1, 1 - T, 0 + T]
            m_color = rgb_to_color(rgbcolor)
            upd_dot = Dot(color=m_color, radius=0.5)
            upd_dot.shift(2*DOWN)
            obj.become(upd_dot)

        dot = Dot()
        dot.add_updater(update_color)

        self.add(dot)

        tracker_label = DecimalNumber(
            tracker.get_value(),
            color=WHITE,
            num_decimal_places=8,
            show_ellipsis=True
        )
        tracker_label.add_updater(
            lambda mob: mob.set_value(tracker.get_value())
        )
        self.add(tracker_label)


        self.play(
            Rotate(dot, -360*DEGREES,
                   about_point=ORIGIN,
                   rate_func=rate_functions.smooth),
            tracker.animate.set_value(1)
            run_time=4
        )
        self.wait()

Upvotes: 3

NickGreefpool
NickGreefpool

Reputation: 91

Maybe something like this could work for you

class ColoredDot(Scene):
    def construct(self):
    
        tracker = ValueTracker(0)
    
        def update_color(obj):
            T=tracker.get_value()
            rgbcolor=[1,1-T,0+T]
            m_color=rgb_to_color(rgbcolor)
            upd_dot=Dot(color=m_color)
            obj.become(upd_dot)
        
        dot=Dot()
        dot.add_updater(update_color)
        self.add(dot)
    
        self.play(tracker.set_value,1,run_time=5)
        self.wait()

where the specific color choice is given by the line

rgbcolor=[1,1-T,0+T]

and the parameter T ranges from 0 to 1. This gives you values for rgb colors that depend on that parameter T. You can change this to any function of T you like to give you whatever color change you need. If you want a periodic change, use something like np.sin(T) and change the ranges of T to (0,2*pi), and I would also set the rate_func to linear at that point.

Upvotes: 4

Related Questions