在常用的动画效果中,介绍了一些元素的创建,销毁,移动和变换的方法,这些方法都是针对单个动画的。
如果需要多个动画互相关联,或者元素需要有更复杂的运动方式,那么,仅仅依靠常用的动画效果可能就无法满足要求了。
本篇的高级动画效果主要介绍一些更加灵活的元素运动方式,如何组合多个动画,以及如何联动多个动画的方式。
掌握了这些方法,就能够表达出更加复杂的数学几何动画。
常用的动画一般都是直线运动或者圆弧运动,而 MoveAlongPath
可以让元素沿着任意的函数轨迹来运动。
下面的示例是一个点沿着一个较为复杂的三角函数形成的路径运动。
cos_func = FunctionGraph(
lambda t: np.cos(t) + 0.5 * np.cos(7 * t) + (1 / 7) * np.cos(14 * t),
color=RED,
)
sc.add(cos_func)
d1 = dot(cos_func.get_start())
sc.play(MoveAlongPath(d1, cos_func), rate_func=linear, run_time=3)
运行效果:
保留动画的轨迹,可以更好的追踪元素的变化规律。
通过 TracedPath
可以设置保留运动轨迹的效果。
下面的示例是一个点以一定的弧度运行,并将其运行的轨迹绘制出来。
d = dot(RIGHT * 2)
b = TracedPath(d.get_center)
sc.add(d, b)
sc.play(d.animate(path_arc=PI / 4).shift(LEFT * 2))
sc.play(d.animate(path_arc=-PI / 4).shift(LEFT * 2))
运行效果:
在常用的动画效果中,一般都是逐个显示各个动画效果,manim
中提供了几个控制动画组合的方式。
用的较多的两个分别是:
通过 LaggedStart
控制组合的多个动画之间的启动时间间隔。
下面的示例是一个点先启动,但是要运行1秒才到达终点,
另一个点延迟0.5秒启动,但是运行0.5秒就到达终点,所以两个点最终应该同时到达。
d1 = dot(LEFT * 2 + UP, color=RED)
d2 = dot(LEFT * 2 + DOWN)
dl = DashedLine(
RIGHT * 2 + UP * 3,
RIGHT * 2 + DOWN * 3,
dash_length=0.1,
dashed_ratio=0.8,
stroke_width=2,
color=GREEN,
)
sc.add(d1, d2, dl)
sc.wait(0.5)
ani1 = d1.animate(run_time=1).shift(RIGHT * 4)
ani2 = d2.animate(run_time=0.5).shift(RIGHT * 4)
sc.play(LaggedStart(ani1, ani2, lag_ratio=0.5))
运行效果:
通过 Succession
控制多个动画顺序执行,它能够保证上一个执行成功后才执行下一个。
下面的示例是4个不同颜色的点,每个点移动成功之后,移动下一个点。
dot1 = Dot(point=LEFT * 2 + UP * 2, radius=0.16, color=BLUE)
dot2 = Dot(point=LEFT * 2 + DOWN * 2, radius=0.16, color=MAROON)
dot3 = Dot(point=RIGHT * 2 + DOWN * 2, radius=0.16, color=GREEN)
dot4 = Dot(point=RIGHT * 2 + UP * 2, radius=0.16, color=YELLOW)
sc.add(dot1, dot2, dot3, dot4)
sc.play(
Succession(
dot1.animate.move_to(dot2),
dot2.animate.move_to(dot3),
dot3.animate.move_to(dot4),
dot4.animate.move_to(dot1),
)
)
运行效果:
动画联动是比动画组合更复杂的一种模式,动画组合时,每个动画其实是固定的,只是启动的时机不一样。
而在动画联动中,一个动画如何运行是完全基于另一个动画的,而不是实现预设的。
下面的示例是一个角度的联动效果,
初始元素有:
line1
和 line_moving
组成的角度a
tex
theta_tex
。初始角度 110°
,然后可以看到随着 line_moving
的移动(先变成 90°
,再增加 140°
),
a
,tex
和theta_tex
的联动效果。
rotation_center = LEFT
theta_tracker = ValueTracker(110)
line1 = Line(LEFT, RIGHT)
line_moving = Line(LEFT, RIGHT)
line_ref = line_moving.copy()
line_moving.rotate(theta_tracker.get_value() * DEGREES, about_point=rotation_center)
a = Angle(line1, line_moving, radius=0.5, other_angle=False)
tex = MathTex(r"\theta").move_to(
Angle(
line1, line_moving, radius=0.5 + 3 * SMALL_BUFF, other_angle=False
).point_from_proportion(0.5)
)
theta_tex = Tex(
r"$\theta = $",
str(int(theta_tracker.get_value())),
r"$^\circ$",
font_size=50,
color=RED,
).shift(UP * 2)
sc.add(line1, line_moving, a, tex, theta_tex)
sc.wait()
line_moving.add_updater(
lambda x: x.become(line_ref.copy()).rotate(
theta_tracker.get_value() * DEGREES, about_point=rotation_center
)
)
a.add_updater(
lambda x: x.become(Angle(line1, line_moving, radius=0.5, other_angle=False))
)
tex.add_updater(
lambda x: x.move_to(
Angle(
line1, line_moving, radius=0.5 + 3 * SMALL_BUFF, other_angle=False
).point_from_proportion(0.5)
)
)
theta_tex.add_updater(
lambda x: x.become(
Tex(
r"$\theta = $",
str(int(theta_tracker.get_value())),
r"$^\circ$",
font_size=50,
color=RED,
).shift(UP * 2)
)
)
sc.play(theta_tracker.animate.set_value(90))
sc.play(theta_tracker.animate.increment_value(140), run_time=3)
运行效果:
本篇介绍的高级动画效果,其实是一些更加灵活的制作动画的方法。
利用这些方法,可以更加方便的定制自己的动画效果。
本篇介绍的高级动画效果和上一篇的常用动画效果可以理解成软件的VIP功能和免费功能,
如果免费功能够用,尽量使用免费功能,免费功能满足不了要求的时候,再考虑VIP功能。
本文关联的微信视频号短视频: