首页 / 文档中心 / 进阶

Manim Transform 家族:Transform、ReplacementTransform、MatchingTex 用法与区别

发布于 2026-11-02 · 进阶系列 · 约 3 分钟读完 · 中文正文 + English TL;DR
▶ 渲染效果实录(manim 渲染输出,代码见正文,可直接复现)
English TL;DR

Transform is where Manim beginners lose track of object identity, so this chapter fixes the mental model first: Transform(a, b) mutates a so that it ends up looking like b — afterwards the object on screen is still a, and b was never added. ReplacementTransform(a, b) removes a and inserts b as the new identity. Choose by what you will reference next scene. Then the family tour: TransformFromCopy keeps the original, FadeTransform cross-fades instead of point-morphing, TransformMatchingShapes aligns submobject geometry automatically, and TransformMatchingTex is the star for equation derivations — it matches LaTeX fragments so unchanged parts stay rock-still while moved terms slide. Also covered: .animate chains, shift/rotate/scale shortcuts, clock/counterclockwise variants, and the documented pitfall of mixing .animate on a group and its submobjects in a single play() call.

先搞懂:Transform 之后,对象是谁?

这是 Manim 变换的第一坑。Transform 改变的是"外观",不替换"身份":

sq = Square()
ci = Circle()
self.play(Transform(sq, ci))
# 此后画面上是"长得像圆的 sq", 继续 play(sq.animate...) 才有效
# ci 从未真正出现在画面上

ReplacementTransform 则相反——旧对象销毁,新对象接管画面,之后的操作要对着新对象写:

self.play(ReplacementTransform(sq, ci))
# 此后请操作 ci, sq 已被移除

选择标准:变换完成后你要继续用哪个变量操作,就选对应语义的那个。教学中最常用 ReplacementTransform(公式推导)和 Transform(同概念变形,比如一个方块一直变到结尾)。

家族成员速览

动画行为典型用途
Transform(a, b)a 变形为 b 的样子,身份不变同一对象的形变叙事
ReplacementTransform(a, b)a 消失,b 接管公式推导、状态切换
TransformFromCopy(b, a)从 b 的复制体变到 a"从这个式子提出一项"
FadeTransform(a, b)交叉淡化,不逐点变形差异太大、变形会乱的场景
TransformMatchingShapes(a, b)按子对象几何自动配对普通图形互变
TransformMatchingTex(a, b)按 LaTeX 片段配对公式推导首选
ClockwiseTransform顺时针路径变形强调旋转关系

公式推导:TransformMatchingTex 实战

推导二次方程求根公式的关键两步:

from manim import *

class Derivation(Scene):
    def construct(self):
        eq1 = MathTex("x^2", "+", "4x", "=", "5")
        eq2 = MathTex("x^2", "+", "4x", "+", "4", "=", "5", "+", "4")
        eq3 = MathTex("(x+2)^2", "=", "9")

        self.play(Write(eq1))
        # 配平: 相同片段原地不动, 新增的 +4 从天上长出来
        self.play(TransformMatchingTex(eq1, eq2))
        self.wait()
        self.play(TransformMatchingTex(eq2, eq3))
        self.wait()

MatchingTex 按 LaTeX 片段对位:写公式时刻意用空格把"想独立移动的部分"拆成不同片段(如 "x^2", "+", "4x" 三段),变形时未变化的片段纹丝不动——这正是 3b1b 公式动画干净利落的秘密。

TransformFromCopy:留下原件

eq = MathTex("a", "=", "b", "+", "c")
target = MathTex("b")
target.next_to(eq, DOWN)
# 从 eq 里的 b 复制一份飞下来, 原式不变
self.play(TransformFromCopy(eq[2], target))

.animate:属性级变换

不换对象、只改属性时,.animate 比 Transform 干净得多:

self.play(square.animate.scale(1.5).rotate(PI / 4).set_color(RED))
# 移动到某点 / 对齐某物也行
self.play(square.animate.next_to(circle, LEFT, buff=0.5))

官方文档明确的坑(0.22.1 版还在强调):同一次 play() 里,不要对"一个组"和"组内的子对象"同时使用 .animate——插值会互相打架出现残影。要么整组一起动,要么拆成两次 play。

节奏与路径控制

# 指定变形路径弧度: 弧线飞行而不是直线
self.play(TransformFromCopy(a, b), path_arc=-90 * DEGREES)

# 时长与缓动
self.play(Transform(s, c), run_time=2, rate_func=there_and_back)

更多编排手段(LaggedStart、Succession)见动画编排。