Manim文档及源码笔记-CE教程BE04英文笔记速览版
Updater Functions _ Mathematical Animations WITH EASE
前言
这次筛选到了Behackl博士的教程,逐步拆解,更为细腻~
参考视频在此【或请自行搜索上面的英文标题】;
本页中文版传送门【建设中】;
更新【new】:
- 8月23日
-
- 文首标注了“前言”与“正文”;
-
- 本系列暂告段落,升级了系列目录,放到了文尾;
- 后续更新备忘:文中“【建设中】”的内容;欢迎朋友们催更~
首先,国际通则:Just GET STARTED~ JUST DO IT~
然后,让我们行动起来~
注:
1、代码实践过程根据运行环境及笔记需要略有改动;
2、经过实践理解,加入了一些自己的注释;
3、常见问题及大概率解决方案:
- Python相关:注意缩进、冒号,中英文字符、大小写;
- Manim相关:安装与运行环境;
- Coding相关:检查拼写;
正文
What is an Updater Function?
- Special function that is called right before Manim captures a new frame
- … can be attached to Mobjects( “Mobject updater”) or the Scene itself( “Scene updater”)
- … can depend on time passed since last rendered frame( “time dependent updaters”)
Why are updaters useful?
- Mobjects can be made dependent on other mobjects!
- Example: make a label move with its mobject:
%%manim -v WARNING -qm HelloDot
class HelloDot(Scene):
def construct(self):
blue_dot=Dot(color=BLUE)
dot_label=Text("Hello dot!").next_to(blue_dot, UP)
dot_label.add_updater(
lambda mobject: mobject.next_to(blue_dot, UP)
)
self.add(blue_dot,dot_label)
self.play(blue_dot.animate.shift(RIGHT))
self.play(blue_dot.animate.scale(3))
self.play(blue_dot.animate.center())
HelloDot
Updater Function Signature
Important: This is valid for up to Manim v0.15.1.Devs do not like this interface and we will likely change ti at some point.
- Mobject Updaters: one or two positional arguments, arbitrary keyword arguments
-
- first argument: the mobject itself
-
- second argument: only if named dt: time difference
- Scene Updaters: one positional argument( time difference), arbitrary keyword arguments
%%manim -v WARNING -qm --disable_caching AllUpdaterTypes
class AllUpdaterTypes(Scene):
def construct(self):
red_dot=Dot(color=RED).shift(LEFT)
pointer=Arrow(ORIGIN, RIGHT).next_to(red_dot,LEFT)
pointer.add_updater( # place arrow left of dot
lambda mob: mob.next_to(red_dot, LEFT)
)
def shifter(mob, dt): # make dot move 2 munits RIGHT/sec
mob.shift(2*dt*RIGHT)
red_dot.add_updater(shifter)
def scene_scaler(dt): # scale mobjects depending on distance to ORIGIN
for mob in self.mobjects:
mob.set(width=2/(1+np.linalg.norm(mob.get_center())))
self.add_updater(scene_scaler)
self.add(red_dot,pointer)
self.update_self(0)
self.wait(5)
AllUpdaterTypes
Useful hints regarding updaters
- Common pitfall: assigning updaters in a loop! Due to scoping in Python, loop variable needs to be added explicitly to updater as keyword argument:
for i in range(len(mob_list)):
mob_list[i].add_updater(lambda mob, dt, i=i: <code involving i>)
- Updaters( Ofter~) keep running through animations! Control via .suspend_updating(), .resume_updating()
- Updaters are resumed automatically after playing an animation
- Without time-based updater, wait will produce static frame:
pass self.wait(frozen_frame=False) to avoid!
%%manim -v WARNING -qm UpdaterAndAnimation
class UpdaterAndAnimation(Scene):
def construct(self):
red_dot=Dot(color=RED).shift(LEFT)
rotating_square=Square()
rotating_square.add_updater(
lambda mob, dt: mob.rotate(PI*dt)
)
def shifter(mob, dt):
mob.shift(2*dt*RIGHT)
red_dot.add_updater(shifter)
self.add(red_dot, rotating_square)
self.wait(1)
red_dot.suspend_updating()
self.wait(1)
self.play(
red_dot.animate.shift(UP),
rotating_square.animate.move_to([-2,-2,0])
)
self.wait(1)
UpdaterAndAnimation
Depending on a number: ValueTracker
- ValueTracker are invisible mobjects that store numbers
- … lets us use Manim’s animation mechanisms to animate modification fo a parameter!
def construct(self):
line=NumberLine(x_range=[-5,5])
position=ValueTracker(0) # assign initial value of tracker
pointer=Vector(DOWN)
pointer.add_updater( # stick pointer to tracked position
lambda mob: mob.next_to(
line.number_to_point(position.get_value()),UP
)
)
pointer.update() # manual execution of update function
self.add(line, pointer)
self.wait()
self.play(position.animate.set_value(4)) # change tracker value
self.play(position.animate.set_value(-2)) # ... and to -2
%%manim -v WARNING -qm --disable_caching ValueTrackerPlot
class ValueTrackerPlot(Scene):
def construct(self):
a=ValueTracker(1)
ax=Axes(x_range=[-2,2,1],y_range=[-8.5,8.5,1],x_length=4,y_length=6)
parabola=ax.plot(lambda x: x**2, color=RED)
parabola.add_updater(
lambda mob: mob.become(ax.plot(lambda x: a.get_value() * x**2, color=RED))
)
a_number=DecimalNumber(
a.get_value(),
color=RED,
num_decimal_places=3,
show_ellipsis=True
)
a_number.add_updater(
lambda mob: mob.set_value(a.get_value()).next_to(parabola, RIGHT)
)
self.add(ax,parabola,a_number)
self.play(a.animate.set_value(2))
self.play(a.animate.set_value(-2))
self.play(a.animate.set_value(1))
ValueTrackerPlot
本系列目录【new】
Manim文档及源码笔记-CE教程BE01英文笔记速览版
Manim文档及源码笔记-CE教程BE02英文笔记速览版
Manim文档及源码笔记-CE教程BE03英文笔记速览版
Manim文档及源码笔记-CE教程BE04英文笔记速览版【本文】
Manim文档及源码笔记-CE教程BE05英文笔记速览版