让你的动画“活”过来:Manim 节奏控制指南 (Rate Functions)

你在制作Manim动画时,是否遇到过这样的困境?

"代码写得天衣无缝,运行流畅,出来的动画却总觉得哪里不对劲?"

虽然物体确实从 A 移动到了 B,但看起来就像是老旧的工业机器人在干活------僵硬、死板,甚至有点无聊。

其实,你的动画离 "丝滑""专业" ,往往只差这一个参数的距离:rate_func (速率函数)

今天,我们就来聊聊 Manim 中这个不起眼但至关重要的参数,看看如何通过控制 "时间的流速",让你的数学动画不仅能动,而且动得有节奏、有灵魂。

1. 什么是 Rate Function?(给时间的进度条)

Manim 中,当你写下 .animate.shift(RIGHT) 时,默认发生了什么?

如果你觉得动画只是简单的"在 Run Time 时间内移动距离 RIGHT",那只对了一半。Rate Function 本质上是动画完成度与时间的关系

想象一下你在看视频时的进度条:

  • 输入 ( t ):当前时间过去了多少(从 0 到 1,代表 0% 到 100% 的时间)。
  • 输出 ( f(t) ):动画实际上完成了多少(从 0 到 1,代表 0% 到 100% 的进度)。

默认的魔法Smooth

Manim 的默认 rate_funcsmooth

这符合物理世界的惯性定律:起步时慢(加速),中间快,快结束时慢(减速)

这就是为什么默认的动画看起来比较自然。

如果我们把它换成 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

光说不练假把式。下面的示例代码可以直观感受不同函数的区别:

python 复制代码
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(color=TEAL)
            label = Text(label_text, font_size=20).next_to(dot, LEFT)
            row = VGroup(label, dot)
            group.add(row)

        # 竖直排列
        group.arrange(DOWN, buff=0.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_func=func, run_time=3).shift(RIGHT * 4))

        self.play(*anims)

运行后你会发现,虽然大家的 run_time 都是3秒,移动距离一样,但"性格"截然不同。


4. 进阶:自定义与时间扭曲

作为会 Python 的老手,如果内置函数满足不了你怎么办?

4.1. 自定义函数 (Lambda大法)

rate_func 接受任何一个 Python 函数。

比如,你想做一个简单的"先慢后快"的加速效果,可以直接用 Lambda

python 复制代码
# y = x^2,典型的加速曲线
class CustomRateFuncDemo(Scene):
    def construct(self):
        # 创建一个圆
        circle = Circle(radius=0.5, color=BLUE).shift(LEFT * 2)
        self.add(circle)

        # 使用自定义 rate_func(t**2)让圆向右移动
        self.play(circle.animate(rate_func=lambda t: t**2).shift(RIGHT * 4), run_time=3)
        self.wait()

4.2. 时间挤压 (Squish Rate Func)

这是 Manim 中最强大的黑科技之一:squish_rate_func

假设你写了一个 run_time=6 的动画,但你希望某个特定的变换(比如变色),

在第 1.2 秒到第 3 秒之间(即整个进度的 0.20.5)由白色 变成红色

在第 3 秒到第 4.8 秒之间(即整个进度的 0.50.8)由红色 变成绿色

你不需要把动画拆成多段写,只需要:

python 复制代码
class SquishRateFuncDemo(Scene):
    def construct(self):
        # 创建一个圆点
        dot = Dot(color=WHITE).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_time=6,
        )
        self.wait()

这个技巧在制作复杂的多重同步动画时非常有效!

5. 总结

Manim 不仅仅是动画工具,它更像是一个导演工具。

  • linear 是为了表现机械、循环。
  • smooth 是为了表现自然、物理。
  • there_and_back / wiggle 是为了引导观众的注意力。
  • squish_rate_func 是为了精准控制时间轴。

下次当你的动画看起来略显生硬时,不妨停下来想一想:"这个动作的节奏对吗?是不是该换个 rate function 了?"

相关推荐
wang_yb1 天前
别急着转投 Polars!Pandas 3.0 带着“黑科技”杀回来了
python·databook
wang_yb12 天前
数据分析师的基本功总结
大数据·databook
wang_yb17 天前
manim边做边学--文字创建销毁的打字机效果
databook·manim
wang_yb19 天前
AI辅助编程下的软件分层设计:让生成的代码井然有序
ai·databook
wang_yb2 个月前
Manim实现旋转扭曲特效
databook·manim
wang_yb2 个月前
Manim实现渐变填充特效
databook·manim
wang_yb2 个月前
Manim实现波浪形文字特效
databook·manim
wang_yb2 个月前
Manim实现闪电特效
databook·manim
wang_yb2 个月前
让YOLO飞起来:从CPU到GPU的配置指南
ai·databook