ChangeSpeed
类是Manim
库中用于修改动画速度的类。
它提供了一种灵活的方式来控制动画的播放速度,使动画在不同时间段内以不同的速度播放,从而创造出更加丰富多样的动画效果。
比如,在创建包含多个元素动画的场景中,通过ChangeSpeed
可以精确控制不同元素在不同时间点的移动速度,实现复杂的动画节奏编排。
1. 动画概述
与之前介绍的那些动画类不同,ChangeSpeed
不是为元素实现某种具体的动画效果,
它的作用对象是动画本身,它的主要特点有:
- 灵活的速度调整:可以指定动画在不同时间对应的速度因子,也就是在动画的不同阶段设置不同的速度
- 与多种动画类型结合:不仅可以用于修改单个动画的速度,还能处理
AnimationGroup
类型的动画,将多个动画组合成一个整体进行速度控制 - 支持速率函数覆盖:通过
rate_func
参数可以覆盖传入动画的速率函数,从而进一步自定义动画的速度变化曲线
主要参数有:
参数名称 | 类型 | 说明 |
---|---|---|
anim | Animation | 需要修改速度的动画对象 |
speedinfo | dict | 指定在不同时间点的动画速度 |
rate_func | func | 覆盖传入动画的速率函数,在修改速度之前应用 |
affects_speed_updaters | bool | 决定是否影响通过add_updater 方法添加的更新器的速度 |
speedinfo
参数是一个字典,
它的key
是动画运行时间的百分比(0 到 1 之间的浮点数),value
是对应的速度因子。
affects_speed_updaters
参数一般在做联动动画时使用的,用来决定是否影响联动动画的速度。
ChangeSpeed
还有一些方法,可以用于全面控制动画的执行流程、时间相关属性和相关对象的处理。
名称 | 说明 |
---|---|
add_updater | 用于将速度变化应用于更新器 |
begin | 在动画开始时被调用时,进行初始化操作 |
finish | 动画结束时被调用 |
update_mobjects | 更新相关对象,如起始对象和(对于变换动画)目标对象 |
clean_up_from_scene | 在动画结束后清理场景 |
get_scaled_total_time | 返回动画所花费的时间 |
interpolate | 在动画的每一帧被调用,用于设置动画的进度 |
2. 使用示例
下面通过示例来演示如何使用ChangeSpeed
类来丰富动画的表现效果。
2.1. 变速移动的点
此示例在场景中创建了两个点,然后使用ChangeSpeed
类来控制其移动动画。
通过speedinfo
参数,设置第一个先减速移动,然后再加速移动,最后再次减速移动。
第二点与第一个点的速度变化正好相反,并且两个点在运动过程中都采用线性速率函数。
d1 = Dot(color=BLUE) d2 = Dot(color=RED) self.add(d1, d2) # 先慢后快再慢 self.play( ChangeSpeed( d1.animate(run_time=2).shift(RIGHT * 5), speedinfo={0.2: 0.5, 0.3: 2, 0.8: 0.5}, rate_func=linear, ), ) # 先快后慢再快 self.play( ChangeSpeed( d2.animate(run_time=2).shift(LEFT * 5), speedinfo={0.2: 2, 0.3: 0.5, 0.8: 2}, rate_func=linear, ), )
2.2. 变速旋转的正方形
先添加了一个正方形,然后利用ChangeSpeed
类来调整其旋转动画。
根据speedinfo
设定,正方形在动画开始的前 30%
时间内慢速旋转(速度因子为 0.5
),之后在 70%~100%
时间内快速旋转(速度因子为 2
),
同时使用平滑的速率函数,产生了变速旋转的动画效果。
square = Square() # 正方形先慢速旋转 然后快速旋转 self.play( ChangeSpeed( Rotate(square, angle=PI, run_time=3), speedinfo={0.3: 0.5, 0.7: 2}, rate_func=smooth, ) )
2.3. 结合更新器的变速缩放
首先创建了一个圆,并定义了一个更新器函数,使圆在每一帧渲染时按一定比例持续缩放。
接着通过ChangeSpeed
类的静态方法add_updater
将更新器应用到圆上,并根据speedinfo
参数,使得更新器在动画中间部分速度变慢,从而实现了圆的变速缩放效果。
注意,这里要设置affects_speed_updaters=True
,否则圆会匀速放大,使得speedinfo
参数无效。
circle = Circle() self.add(circle) # 定义一个更新器函数,使圆持续缩放 def update_circle(circle, dt): circle.scale(1 + 0.1 * dt) # 将更新器添加到圆上,并使用ChangeSpeed控制更新器的速度 ChangeSpeed.add_updater(circle, update_circle) self.play( ChangeSpeed( Wait(4), speedinfo={0.3: 2, 0.4: 0.4, 0.7: 0.4, 1: 2}, affects_speed_updaters=True, ) )
2.4. 动画组中元素的不同速度
在场景中添加了两条水平方向且一上一下的直线,通过ChangeSpeed
类作用于AnimationGroup
来实现不同速度的动画效果。
因为speedinfo
参数只能设置一种速度因子,为了使两条直线的变色速度不一样,这里使用了一个技巧,设置两条直线变色的run_time
不一样。
这样,即使它们的speedinfo
参数一样,最终还是以不同节奏来变色。
l1 = Line(LEFT * 3, RIGHT * 3).shift(UP) l2 = Line(LEFT * 3, RIGHT * 3).shift(DOWN) self.add(l1, l2) # 创建一个动画组,使两条线以不同的速度变色 self.play( ChangeSpeed( AnimationGroup( l1.animate(run_time=2).set_color(RED), l2.animate(run_time=4).set_color(BLUE), ), speedinfo={ 0.3: 1, 0.6: 0.5, 1: 1, }, rate_func=linear, ) )
3. 附件
文中的代码只是关键部分的截取,完整的代码共享在网盘中(change_speed.py
),
下载地址: 完整代码 (访问密码: 6872)