Manim 怎么给公式里的某一项单独上色?MathTex 的三种写法
2026 年 11 月 8 日 · 极坐标⋅XYZ
Manim 怎么给公式里的某一项单独上色?MathTex 的三种写法
先让这一项成为公式里单独的一段,再给这一段上色。MathTex 默认把整串字符当成一个整体,抓不出其中一项;做法有三种:创建时传 tex_to_color_map={"c": YELLOW} 一步上色;传 substrings_to_isolate=["c"] 隔离后再用 set_color_by_tex("c", YELLOW) 上色;或者把公式拆成多个字符串 MathTex("a^2", "+", "b^2", "=", "c^2"),再用 eq[4].set_color(YELLOW) 按下标上色。三种效果一样,看哪种顺手用哪种。
Manim 是 3Blue1Brown 的 Grant Sanderson 写的数学动画引擎,画面是用 Python 代码一步步描述出来的;现在多数人用的是社区维护的 Manim Community。本文的写法按 2026 年的 Manim 0.21.0 整理,这是极坐标⋅XYZ 工作区和 App 装的版本。想了解它是什么,可以看这篇介绍;想按顺序系统学,极坐标⋅XYZ 上有按 0.21.0 做的 2026 年最新 Manim 中文教程,公式上色在《文本与公式》那一课里。
下面的完整代码都能在极坐标⋅XYZ 的工作区里直接运行,点代码块上方的「在工作区中打开」即可,工作区装的是同一版本,不用在电脑上装环境。
最小可运行的例子:三种写法放在一起
同一条勾股定理公式,分别用三种写法给不同的项上色,上中下排开方便对比:
from manim import *
class ColorOnePartThreeWays(Scene):
def construct(self):
# 方式一:创建时传 tex_to_color_map,一步上色
eq1 = MathTex(
r"a^2 + b^2 = c^2",
tex_to_color_map={"a": BLUE, "b": GREEN, "c": YELLOW},
)
# 方式二:先 substrings_to_isolate 隔离,之后任意时刻 set_color_by_tex
eq2 = MathTex(
r"a^2 + b^2 = c^2",
substrings_to_isolate=["a", "b"],
)
# 方式三:拆成多个字符串,按下标点名
eq3 = MathTex("a^2", "+", "b^2", "=", "c^2")
group = VGroup(eq1, eq2, eq3).scale(1.4).arrange(DOWN, buff=0.9)
self.play(Write(group))
self.play(eq2.animate.set_color_by_tex("a", BLUE))
self.play(eq3[0].animate.set_color(BLUE))
self.wait()
第一行创建时就带着颜色;第二行和第三行先是白色,后面两步动画分别把 a^2 里的 a、和整个 a^2 染成蓝色。
为什么是这样:先隔离,才能点名
MathTex 把你给的字符串交给 LaTeX 排版,再按你传入的字符串个数切成子对象。传一整串,就只有一个子对象,里面的每个字形混在一起,上色只能整条一起染。三种写法其实是同一件事:想办法在排版时把目标那一项切成独立的一段,区别只在切的方式和上色的时机。
| 写法 | 怎么切出那一项 | 怎么上色 | 适合 |
|---|---|---|---|
tex_to_color_map |
传入的字典 key 自动被隔离 | 创建时一步完成 | 颜色一开始就定好 |
substrings_to_isolate + set_color_by_tex |
传入的子串被隔离 | 之后任意时刻调用,可放进 .animate |
分步骤逐项上色 |
| 拆成多个字符串 + 下标 | 你自己决定每一段怎么断 | eq[i].set_color(...) |
最直接,下标一看就懂 |
多个字符串的写法里,MathTex("a^2", "+", "b^2", "=", "c^2") 有 5 个子对象,eq[0] 是 a^2,eq[4] 是 c^2,用法和列表一样。
常见写错的地方
整串不拆,直接 set_color_by_tex
eq = MathTex("a^2 + b^2 = c^2")
eq.set_color_by_tex("c", YELLOW) # 没有任何变化,也不报错
整串只有一段,里面没有单独的「c」可匹配。要么传 substrings_to_isolate=["c"],要么改用 tex_to_color_map,要么拆成多个字符串。
{{ }} 里带了空格
eq = MathTex("{{ a^2 }} + {{ b^2 }} = {{ c^2 }}")
eq.set_color_by_tex("c^2", YELLOW) # 对不上
set_color_by_tex 拿你给的字符串和每一段精确比较,{{ c^2 }} 圈出来的是前后带空格的「 c^2 」,和 "c^2" 对不上,同样不报错。去掉空格写成 {{c^2}},或者改用多个字符串的写法。这个现象在上一篇 Text、Tex、MathTex 的区别里有五种写法的完整对照。
以为 "x" 会染上所有含 x 的地方
set_color_by_tex("x", ...) 只认正好是「x」的那一段,不会把 x^2、2x 里的 x 一起染上。要染 x^2 就把 "x^2" 作为一个整体隔离出来。
常见追问(FAQ)
Q:三种写法该选哪一种?
A:颜色一开始就确定,用 tex_to_color_map;要分步骤、一项项在动画里上色,用 substrings_to_isolate 加 set_color_by_tex;公式不长、想最直观,直接拆成多个字符串按下标取。
Q:上色可以做成动画吗?
A:可以。把调用放进 .animate,比如 eq.animate.set_color_by_tex("a", BLUE) 或 eq[0].animate.set_color(BLUE),颜色就会渐变过去,上面的例子里就是这样写的。
Q:公式里有中文能这样上色吗?
A:MathTex 里直接写中文会编译报错,中文请用 Text,纯数学公式才放进 MathTex,两者怎么选见上一篇。
这个知识点在教程《文本与公式》的「公式分组与上色」一节里有配套视频和可改的代码,课里把上面三种写法依次演示了一遍;想直接动手,打开工作区,把上面的代码贴进去点运行。
来源:极坐标⋅XYZ · jizuobiao.xyz · 更新于 2026-11-08 · 基于 Manim Community 0.21.0