Manim 节奏控制指南 (Rate Functions) 什么是 Rate Function给时间的进度条在Manim中当你写下.animate.shift(RIGHT)时默认发生了什么如果你觉得动画只是简单的“在Run Time时间内移动距离RIGHT”那只对了一半。Rate Function本质上是动画完成度与时间的关系。想象一下你在看视频时的进度条输入 (t)当前时间过去了多少从 0 到 1代表 0% 到 100% 的时间。输出 (f(t))动画实际上完成了多少从 0 到 1代表 0% 到 100% 的进度。默认的魔法SmoothManim 的默认rate_func是smooth。这符合物理世界的惯性定律起步时慢加速中间快快结束时慢减速。这就是为什么默认的动画看起来比较自然。如果我们把它换成linear线性物体就会瞬间以最大速度启动最后瞬间急停看起来就会很像“PPT 动画”。2. 常用函数图鉴选对“调味料”Manim内置了一大堆写好的函数位于manim.utils.rate_functions。我们可以把它们看作是给动画调味的香料。为了方便演示我们假设我们要移动一个小球。2.1. 基础三剑客linear(匀速)效果机械感强速度恒定。适用场景旋转的齿轮、循环滚动的背景、匀速扫描的雷达。smooth(默认)效果两头慢中间快。适用场景绝大多数物体的移动、缩放。rush_into/rush_from效果rush_into: 越走越快最后“砰”地撞线只有加速。rush_from: 一开始很快慢慢停下来只有减速。适用场景连续动作的衔接。比如小球飞入画面停下rush_from或者发射出去rush_into。2.2. 动感特效组there_and_back(往返)效果走到终点又原路返回起点。适用场景强调某个东西。比如把公式放大一下再缩回去告诉观众“看这里”。wiggle(摆动)效果像果冻一样左右晃动一下。适用场景表示“错误”、“拒绝”或者引起注意。running_start(助跑)效果先向后退一点点然后猛地向前冲。适用场景想要表现物体很有力量感或者像卡通片里的冲刺效果。2.3. 物理模拟组ease_out_bounce(落地反弹)效果像篮球落地一样到底部后弹跳几次再停下。适用场景文字掉落、物体自由落体。3. 动手写个 Demo光说不练假把式。下面的示例代码可以直观感受不同函数的区别from manim import * class RateFuncComparison(Scene): def construct(self): # 定义我们想对比的函数 funcs [ linear, smooth, rush_from, rush_into, there_and_back, rate_functions.ease_out_bounce, ] labels [ Linear, Smooth, Rush Into, Rush From, There Back, Bounce, ] # 创建圆点和文字 group VGroup() for i, (func, label_text) in enumerate(zip(funcs, labels)): dot Dot(colorTEAL) label Text(label_text, font_size20).next_to(dot, LEFT) row VGroup(label, dot) group.add(row) # 竖直排列 group.arrange(DOWN, buff0.5).to_edge(LEFT) self.add(group) # 制作动画让所有点同时向右移动 # 注意我们在这里分别指定了不同的 rate_func anims [] for item, func in zip(group, funcs): dot item[1] # 获取组里的 Dot anims.append(dot.animate(rate_funcfunc, run_time3).shift(RIGHT * 4)) self.play(*anims)运行后你会发现虽然大家的run_time都是3秒移动距离一样但“性格”截然不同。4. 进阶自定义与时间扭曲作为会Python的老手如果内置函数满足不了你怎么办4.1. 自定义函数 (Lambda大法)rate_func接受任何一个Python函数。比如你想做一个简单的“先慢后快”的加速效果可以直接用Lambda# y x^2典型的加速曲线 class CustomRateFuncDemo(Scene): def construct(self): # 创建一个圆 circle Circle(radius0.5, colorBLUE).shift(LEFT * 2) self.add(circle) # 使用自定义 rate_funct**2让圆向右移动 self.play(circle.animate(rate_funclambda t: t**2).shift(RIGHT * 4), run_time3) self.wait()4.2. 时间挤压 (Squish Rate Func)这是Manim中最强大的黑科技之一squish_rate_func。假设你写了一个run_time6的动画但你希望某个特定的变换比如变色在第1.2秒到第3秒之间即整个进度的0.2到0.5由白色变成红色在第3秒到第4.8秒之间即整个进度的0.5到0.8由红色变成绿色。你不需要把动画拆成多段写只需要class SquishRateFuncDemo(Scene): def construct(self): # 创建一个圆点 dot Dot(colorWHITE).shift(LEFT * 2) self.add(dot) # 使用UpdateFromAlphaFunc来同时控制位置和颜色变化 def update_dot(obj, alpha): # 位置变化 - 使用默认的linear速率 obj.move_to(LEFT * 2 RIGHT * 5 * alpha) # 颜色变化 - 使用squish_rate_func控制变色的时间段 squished_alpha squish_rate_func(smooth, 0.2, 0.5)(alpha) squished_alpha2 squish_rate_func(smooth, 0.5, 0.8)(alpha) if alpha 0.5: obj.set_color(interpolate_color(WHITE, RED, squished_alpha)) else: obj.set_color(interpolate_color(RED, GREEN, squished_alpha2)) self.play( UpdateFromAlphaFunc(dot, update_dot), run_time6, ) self.wait()这个技巧在制作复杂的多重同步动画时非常有效