在 Manim
动画制作中,Transform
、TransformFromCopy
、ReplacementTransform
和Restore
是四个通用的对象变换动画类。
这几个类能够实现从一个对象到另一个对象的平滑过渡、复制并变换、直接替换以及状态恢复等多种效果。
Transform
:将一个Mobject
平滑地变换为另一个Mobject
TransformFromCopy
:从一个对象复制出一个副本,并将该副本变换为目标对象ReplacementTransform
:将一个Mobject
替换为另一个Mobject
,并且在变换过程中,原始对象会被目标对象完全替代Restore
:将一个Mobject
恢复到其之前保存的状态时使用
通过这些动画类,我们可以清晰地展示对象之间的关系、强调变换过程、突出替换逻辑,以及灵活地在不同状态之间切换。
它们在数学公式推导、图形变换、场景切换等场景中发挥着重要作用,为动画制作提供了强大的工具,帮助创作者以直观且富有表现力的方式呈现复杂的概念和过程。
1. 动画概述
1.1. Transform
Transform
用于将一个Mobject
平滑地变换为另一个Mobject
。比如将一个正方形逐渐变为圆形,或者将一段文本替换为另一段文本。
它常用于数学公式推导、图形变换等场景,能够直观地展示从一种状态到另一种状态的过渡。
Transform
是一个通用的变换类,可以对形状、位置、颜色等多种属性进行变换。
变换过程中,原始对象和目标对象都会保留在场景中,直到动画结束。如果需要在变换后移除原始对象,需要手动操作。
它的参数主要有:
参数名称 | 类型 | 说明 |
---|---|---|
mobject | Mobject | 要被变换的对象 |
target_mobject | Mobject | 变换的目标对象 |
path_arc | float | 如果使用圆形路径,指定点移动的弧度 |
path_func | func | 定义了 mobject 的点在变换过程中所走的路径。可以使用 Manim 提供的路径函数或自定义函数。 |
path_arc_axis | np.ndarray | 如果使用圆形路径,指定旋转的轴 |
path_arc_centers | np.ndarray | 如果设置了此参数且未设置path_func ,则会生成一个沿圆形路径的路径函数。此参数定义了圆形路径的中心。 |
replace_mobject_with_target_in_scene | bool | 控制动画完成后,是否用target_mobject 替换mobject |
1.2. TransformFromCopy
当需要从一个对象复制出一个副本,并将该副本变换为目标对象时使用TransformFromCopy
。例如,在讲解数学公式时,从一个已有的公式中复制一部分并将其变换为新的表达式。
TransformFromCopy
适用于强调某个对象的复制和变换过程,使观众更清楚地看到变换的来源。
TransformFromCopy
实际上是Transform
的一个变体,它先对原始对象进行复制,然后对复制的对象执行变换动画。
原始对象在动画过程中保持不变,变换的是其副本,这使得动画效果更加清晰,避免了原始对象的直接改变。
它的参数类似Transform
的参数。
1.3. ReplacementTransform
ReplacementTransform
用于将一个Mobject
替换为另一个Mobject
,并且在变换过程中,原始对象会被目标对象完全替代。
例如,在展示数学公式推导时,将一个公式直接替换为另一个公式,强调两者的等价性或替换关系。
ReplacementTransform
适用于需要明确表示对象被替换的场景,强调变换的“替代”性质。
ReplacementTransform
继承自Transform
类,但它在变换完成后会移除原始对象,只保留目标对象。
它更强调“替换”的效果,而不是像Transform
那样保留原始对象和目标对象同时存在一段时间。
它的参数类似Transform
的参数。
1.4. Restore
当需要将一个Mobject
恢复到其之前保存的状态时使用Restore
。
例如,在对一个图形进行了一系列复杂的变换后,需要将其恢复到初始状态,或者在展示一个对象的多种变换后,恢复到某个特定的中间状态。
Restore
适用于需要反复展示对象不同状态的场景,如对比不同变换效果、演示可逆变换等。
它需要先通过Mobject.save_state()
方法保存对象的状态,然后才能使用Restore
动画将其恢复。
它的参数主要有:
参数名称 | 类型 | 说明 |
---|---|---|
mobject | Mobject | 要恢复的对象 |
2. 使用示例
下面通过示例来演示这几个转换动画的效果。
2.1. 通用转换Transform
这个示例中,将一个数学公式和一个图形平滑地变换为另一个公式和图形。
变换中,设置了path_arc
参数,以一个弧形的路径变换为目标对象。
# 创建初始公式
f1 = MathTex("a^2 + b^2 = c^2").shift(UP)
# 创建目标公式
f2 = MathTex("c = \\sqrt{a^2 + b^2}").shift(DOWN)# 创建一个正方形
square = Square(side_length=1, color=BLUE).shift(DOWN)
# 创建一个圆形
circle = Circle(radius=0.6).shift(UP)self.add(f1, square)
self.wait()
# 使用 Transform 将公式1变换为公式2,将正方形变换为圆形
self.play(Transform(f1, f2, path_arc=PI),Transform(square, circle, path_arc=PI),
)
2.2. 比较Replace和Copy的不同
通过这个示例,可以了解TransformFromCopy
和ReplacementTransform
两种动画效果的区别,帮助我们根据实际需求选择合适的动画类。
对于TransformFromCopy
:
- 从原始对象复制出一个副本,并对副本进行变换
- 原始对象保持不变,变换的是副本
- 适用于需要保留原始对象的场景
对于ReplacementTransform
:
- 直接将原始对象替换为目标对象
- 原始对象在动画结束后被移除,目标对象取代其位置
- 适用于需要明确表示对象被替换的场景
下面的示例中,TransformFromCopy
每次转换都会保存原对象,而ReplacementTransform
则只保留变换后的目标对象。
# 创建两个相同的正方形作为原对象
s1 = Square().shift(LEFT * 1.5)
s2 = Square().shift(RIGHT * 1.5)# 创建两个圆形作为目标对象
c1 = Circle().shift(LEFT * 1.5)
c2 = Circle().shift(RIGHT * 1.5)t1 = Triangle().shift(LEFT * 1.5)
t2 = Triangle().shift(RIGHT * 1.5)# 添加原对象到场景中
self.add(s1, s2)
self.wait(1)# 添加标题用于区分两种变换
title1 = Text("TransformFrom Copy",t2g={"Copy": [BLUE, RED, YELLOW]},font_size=25,
).next_to(s1, UP)
title2 = Text("Replacement Transform",t2g={"Replacement": [BLUE, RED, YELLOW]},font_size=25,
).next_to(s2, DOWN)
self.add(title1, title2)
self.wait()# 使用 TransformFromCopy 对左边的图形进行变换
# 使用 ReplacementTransform 对右边的图形进行变换
self.play(TransformFromCopy(s1, c1),ReplacementTransform(s2, c2),
)
self.wait()
self.play(TransformFromCopy(c1, t1),ReplacementTransform(c2, t2),
)
2.3. 恢复初始状态Restore
这个示例中,先创建一个六边形,先变换成星形,再经过一系列其他的变换,比如颜色,透明度,移动,放大,翻转等变换。
最后通过Restore
直接恢复成原始状态。
# 创建一个六边形
hexagon = RegularPolygon(n=6)
# 保存六边形的初始状态
self.add(hexagon)
hexagon.save_state()
# 将六边形变换为一个星形
star = Star(color=RED)
self.play(Transform(hexagon, star), run_time=run_time)
self.wait()
self.play(Restore(hexagon))self.play(hexagon.animate.set_color(YELLOW).set_opacity(0.4), run_time=run_time)
self.play(hexagon.animate.shift(RIGHT).scale(2), run_time=run_time)
self.play(hexagon.animate.rotate(PI * 0.75), run_time=run_time)# 使用 Restore 恢复六边形的初始状态
self.play(Restore(hexagon))
3. 附件
文中的代码只是关键部分的截取,完整的代码共享在网盘中(transform.py
),
下载地址: 完整代码 (访问密码: 6872)