Manim 的 Text、Tex、MathTex 有什么区别,该用哪个?中文和公式混排怎么写
2026 年 10 月 20 日 · 极坐标⋅XYZ
Manim 的 Text、Tex、MathTex 有什么区别,该用哪个?中文和公式混排怎么写
写字用 Text,写公式用 MathTex,英文句子里夹公式用 Tex,中文句子里夹公式用 0.21 新增的 Typst。Text 用电脑里的字体直接画字,不认 LaTeX 语法,中文直接写;Tex 和 MathTex 都交给 LaTeX 排版,区别只在默认模式:Tex 默认是正文,公式要用 $...$ 包起来,MathTex 整串都是公式。这两个写中文都要换 ctex 模板,不然 LaTeX 直接报错。Typst 和 MathTypst 是同一套分工换成 Typst 排版,中文直接写,也不用装 LaTeX。
Manim 是 Grant Sanderson 给 3Blue1Brown 做视频写的 Python 动画库,现在大家装的多是社区版 Manim Community。字和公式是数学动画里用得最多的东西,也是新手最容易卡住的地方:同一句话有五六个类能写,报错信息又常常是 LaTeX 的。这篇的结论和数字,我们在 0.21.0 和 2026 年 10 月 8 日发布的 0.22.0 上各跑了一遍,两边一样。不熟悉 Manim 可以先看这篇介绍;想从头系统学,极坐标⋅XYZ 上 2026 年按新版本录的 Manim 中文教程里,文字和公式单独是一课。
标了「在工作区中打开」的代码,点一下就能在极坐标⋅XYZ 的工作区里跑,三段我们都在线上工作区跑过。工作区装的是 Manim 0.21.0,电脑上不用装 Python,也不用装 LaTeX。
先看一眼:同一个 1/2,三种写法
from manim import *
class OneHalfThreeWays(Scene):
def construct(self):
a = Text("1/2") # 普通文字:三个字符排成一行
b = MathTex(r"\frac{1}{2}") # LaTeX 排出来的上下分数
c = MathTypst("1/2") # Typst 排出来的上下分数
row = VGroup(a, b, c).scale(2.5).arrange(RIGHT, buff=2.5)
names = VGroup(*[Text(n, font_size=30, color=GRAY) for n in ("Text", "MathTex", "MathTypst")])
for name, m in zip(names, row):
name.move_to([m.get_x(), row.get_bottom()[1] - 0.5, 0], aligned_edge=UP)
self.play(LaggedStart(*[Write(m) for m in row], lag_ratio=0.5))
self.play(FadeIn(names))
self.wait()
Text("1/2") 就是「1」「/」「2」三个字符排一行,和你在记事本里打出来的一样。另外两个是真分数,分子分母上下叠,中间一条分数线。MathTex 要写 LaTeX 的 \frac{1}{2},MathTypst 直接写 1/2,Typst 自己会把它排成分数。
在工作区第一次用 Typst,浏览器要先下载一个十几 MB 的 Typst 编译器,之后走缓存。
怎么选
| 类 | 谁来排版 | 默认是 | 写中文 | 本机要装 | 适合写 |
|---|---|---|---|---|---|
Text |
系统字体 | 普通文字 | 直接写 | 不用额外装 | 标题、说明、标签、中文 |
Tex |
LaTeX | 正文,公式要 $...$ |
要 ctex 模板 | LaTeX | 英文句子里夹公式 |
MathTex |
LaTeX | 公式 | 放进 \text{},也要 ctex |
LaTeX | 单独的公式、要拆开上色或变形的公式 |
Typst |
Typst | 正文,公式要 $...$ |
直接写 | pip install "manim[typst]" |
中文句子里夹公式 |
MathTypst |
Typst | 公式 | 一般不在公式里放中文 | 同上 | 单独的公式,按名字分组上色 |
Typst 和 MathTypst 是 0.21.0 才有的,老教程里看不到。新写的代码要不要换成 Typst,我们的看法是:已经装好 LaTeX、公式都是英文的,继续用 MathTex 没问题,网上的例子也多;要写中文、或者不想装 LaTeX,Typst 省事很多。

Text:写字用它,别在里面写公式
Text 拿系统里的字体把字一个个画成矢量图形,中文英文都行,跟 Word 里打字差不多。它不认任何排版语法,Text("$x^2$") 画出来就是 $、x、^、2、$ 五个字符。想要个上标,可以直接打 Unicode 的「²」,比如上面图里第一行的 a²+b²=c²,但那是字体里现成的上标字符,大小位置都是死的,写复杂一点的公式还是得交给排版引擎。
它快。我们在本机测,进程里第一个 Text 要加载字体,用了 400 毫秒左右,之后每个只要几毫秒;MathTex 每个新公式都要调一次 LaTeX,第一次 0.4~0.7 秒,同样的公式第二次走缓存只要 1 毫秒。一个场景里几十个标签,用 Text 能省不少时间。
常用的几个参数:font_size 改字号(默认 48),font="..." 换成本机装的别的字体,\n 换行、line_spacing 调行距,t2c={"勾股": YELLOW} 把某几个字单独上色,t2w、t2s 同理改粗细和斜体。要在一段话里混好几种样式,还有个 MarkupText,用类似 HTML 的标签写,比如 <span fgcolor="yellow">c²</span>。
Tex 和 MathTex:差一对美元符号
两个都是把字符串塞进一份 LaTeX 文档,编译成 SVG 再读回来。区别在套的环境:
Tex("...")套的是center环境,里面默认是普通正文,要写公式得自己加$...$;MathTex("...")套的是align*环境,整串一进去就是数学模式,不用写美元符号。
所以 Tex(r"The area is $\pi r^2$") 和 MathTex(r"\pi r^2") 里的公式长得一样。纯公式就用 MathTex,省得到处写 $;一句英文里夹个公式,用 Tex。
这里有个容易忽略的差别:Tex 里的 $...$ 是「行内公式」,LaTeX 会把分数、求和这些压扁,好塞进一行字里。我们量了 Tex(r"$\frac{1}{2}$"),高 0.60 个单位,MathTex(r"\frac{1}{2}") 高 1.01,差了快一半。想在 Tex 里要正常大小的分数,写成 $\displaystyle\frac{1}{2}$,量出来也是 1.01。
数学模式还会吃掉空格:MathTex("a b") 和 MathTex("ab") 量出来宽度一模一样,都是 0.45。要空格得写 a\ b 或 a\quad b。另外因为是 align*,MathTex 里可以用 & 和 \\ 写多行对齐的公式,这个在教程「多行公式对齐」那一节里专门讲。
MathTex 可以传好几个字符串,每个字符串变成一个子对象。MathTex("a^2", "+", "b^2", "=", "c^2") 有 5 个子对象,eq[4] 就是 c^2,后面上色和做动画都靠这个。
中文怎么写
在默认设置下,Tex("面积") 和 MathTex(r"\text{面积}") 都会报错,日志里是这么一行:
LaTeX Error: Unicode character 面 (U+9762)
Manim 默认的 LaTeX 模板用 latex 编译,不认中文。有三个办法。
第一个,换 ctex 模板,用 xelatex 编译:
Tex(r"直角三角形中 $a^2+b^2=c^2$", tex_template=TexTemplateLibrary.ctex)
MathTex(r"\text{面积 } S = \pi r^2", tex_template=TexTemplateLibrary.ctex)
前提是本机的 TeX 发行版里有 xelatex 和 ctex 宏包,TeX Live 完整安装就带,MiKTeX 一般会在第一次用到时提示下载。xelatex 比 latex 慢,我们测一个带中文的 Tex 第一次编译要 1 秒多。整个文件都要中文的话,可以在文件顶层写 config.tex_template = TexTemplateLibrary.ctex,不用每个都传。
第二个,中文和公式分开写:中文用 Text,公式用 MathTex,再用 next_to 或 VGroup(...).arrange(RIGHT) 拼在一起。不用装 ctex,缺点是基线要自己对,字号也要调:同样 font_size=48,Text("x") 高 0.30 个单位,MathTex("x") 只有 0.23,拼在一起公式会显得小一号。
第三个,用 Typst。Typst 默认就能排中文,公式写在 $...$ 里,不用装 LaTeX:
from manim import *
class ChineseWithFormula(Scene):
def construct(self):
title = Text("勾股定理", font_size=56).to_edge(UP)
# 中文夹公式:Typst 里用 $...$ 包住公式,中文直接写
line = Typst("直角三角形里,两条直角边的平方和等于斜边的平方:$a^2 + b^2 = c^2$", font_size=40)
line.next_to(title, DOWN, buff=0.6)
# 单独的大公式:{{ … : 名字 }} 分组,之后按名字取出来上色
eq = MathTypst("{{ a^2 + b^2 : lhs }} = {{ c^2 : rhs }}", font_size=96).shift(DOWN * 0.8)
self.play(Write(title))
self.play(FadeIn(line, shift=UP * 0.2))
self.play(Write(eq))
self.play(eq.select("lhs").animate.set_color(BLUE), eq.select("rhs").animate.set_color(YELLOW))
self.wait()
Typst 的公式语法和 LaTeX 不一样,分数直接写 /,求和写 sum_(k=1)^n,{{ ... : 名字 }} 圈起来的部分可以用 .select("名字") 取出来。细节我们在这篇 Typst 用法里写过,这里不重复。
在工作区里写中文,用 Text 或者 Typst。工作区的 LaTeX 公式是浏览器里的 MathJax 排的,MathTex 写英文公式没问题,Tex 的正文模式和 \text{} 里的中文目前排不出来,ctex 模板在浏览器里也用不上。
给公式的一部分上色
讲题的时候经常要把某一项标出来。MathTex 上色有个前提:你要的那一项,得是单独的一段。
from manim import *
class ColorOnePart(Scene):
def construct(self):
# 拆成五段,每段是一个子对象:eq[0] 是 a^2,eq[4] 是 c^2
eq = MathTex("a^2", "+", "b^2", "=", "c^2", font_size=96)
self.play(Write(eq))
self.play(eq.animate.set_color_by_tex("c^2", YELLOW))
self.play(Indicate(eq[4]))
self.wait()
拆段有三种写法,效果一样:像上面这样传多个字符串;在一个字符串里用 {{c^2}} 圈出来;或者传 substrings_to_isolate=["c^2"]。也可以一步到位写 tex_to_color_map={"c^2": YELLOW}。
我们把五种写法挨个试了,有两种不生效,而且不报错:

原因在 set_color_by_tex 的匹配方式。0.21.0 和 0.22.0 里它拿你给的字符串和每一段做精确比较,一个字符都不能差。{{ c^2 }} 圈出来的那一段是带空格的「 c^2 」,和 "c^2" 对不上;整串不拆时只有一段「a^2 + b^2 = c^2」,更对不上。同理,set_color_by_tex("x", ...) 不会把 x^2、2x 里的 x 都染上,只认正好是「x」的那一段。
不想拆段,也能按字形下标直接取:本机用 LaTeX 渲的时候,MathTex("a^2 + b^2 = c^2") 的 eq[0] 是 8 个字形(a、2、+、b、2、=、c、2),eq[0][6:8] 就是 c 和它的上标。下标不好数的时候,临时加一行 self.add(index_labels(eq[0])),每个字形旁边会标出它的编号。
Text 上色用 t2c,MathTypst 用 {{ ... : 名字 }} 加 .select("名字"),上面两段代码里都有。
常见写错的地方
在 Text 里写 LaTeX
Text(r"$\frac{1}{2}$")
画出来就是这一串字符原样,带美元符号和反斜杠。公式交给 MathTex 或 MathTypst。
字符串前面忘了 r
MathTex("\frac{1}{2}") # 少了 r
Python 会把 \f 当成换页符,LaTeX 收到的是一个看不见的字符加上 rac{1}{2},报 Missing $ inserted。我们照这样写,报的就是这个。更麻烦的是不报错的:MathTex("\theta") 里的 \t 被当成制表符,画出来是斜体的「heta」,我们量了宽 0.97 个单位,一个 θ 才 0.2 左右。\n(\nabla)、\b(\beta)也会被 Python 先转义掉,所以 LaTeX 字符串一律写成 r"..."。
Tex 写中文没换模板
报 LaTeX Error: Unicode character 面 (U+9762) 这一类,就是中文进了默认模板。换 TexTemplateLibrary.ctex,或者改用 Text、Typst,见上面「中文怎么写」。
{{ }} 里带了空格,上色没反应
MathTex("{{ a^2 }} + {{ b^2 }} = {{ c^2 }}") 拆出来的段是「 a^2 」「 c^2 」,前后各带一个空格,set_color_by_tex("c^2", ...) 匹配不上,也不报错。去掉空格写成 {{c^2}},或者改用多参数的写法。
Tex 里的分数、求和变小了
单个 $...$ 是行内公式,分数会被压到一行字的高度。要么改用 MathTex,要么在公式前面加 \displaystyle。
常见追问(FAQ)
Q:电脑上没装 LaTeX,还能写公式吗?
A:能。Text 本来就不需要 LaTeX;0.21.0 之后 pip install "manim[typst]" 装上 Typst 支持,Typst 和 MathTypst 就能写公式,Typst 编译器跟着 Python 包一起装,不用单独装 TeX 发行版。不想在本机装任何东西,用极坐标⋅XYZ 的工作区,浏览器打开就有 Text、MathTex 和 Typst。
Q:三个类的字号是一样的吗?
A:font_size 默认都是 48,但字形大小不完全一样。我们量了单个字母 x:Text 高 0.30 个单位,MathTex 高 0.23,MathTypst 也在 0.23 左右。混排时 Text 那边可以调小一点,或者统一用一种。
Q:多行公式怎么让等号对齐?
A:MathTex 里用 & 标对齐点、\\ 换行,比如 MathTex(r"x &= 1 + 1 \\ &= 2")。教程《文本与公式》的「多行公式对齐」一节有完整例子。
Q:一个公式变成另一个公式的动画用什么?
A:TransformMatchingTex,它按拆好的段去配对,所以前面「拆段」那一步同样重要。教程最后一节「公式变换 TransformMatchingTex」专门讲。
Q:0.22.0 在这些地方有变化吗? A:我们没测出差别。文中的尺寸、报错、上色结果在 0.21.0 和 0.22.0 上逐项对过,完全一样。工作区目前装的是 0.21.0。
这些内容在教程《文本与公式》里分成五节:「Text 与字体」「Tex 与 MathTex」「公式分组与上色」「多行公式对齐」「公式变换 TransformMatchingTex」,每节有视频,旁边的代码可以边看边改。想直接动手,打开工作区,把上面的代码贴进去点运行。
来源:极坐标⋅XYZ · jizuobiao.xyz · 更新于 2026-10-20 · 基于 Manim Community 0.21.0,0.22.0 复核