首页 / 文档中心 / 进阶

Manim 文字排版:Text、Paragraph、MarkupText 与中文字体实务

发布于 2026-11-02 · 进阶系列 · 约 3 分钟读完 · 中文正文 + English TL;DR
English TL;DR

Manim's text stack has three layers. Text() is the everyday workhorse: system fonts through Pango, with Chinese supported by font="Microsoft YaHei"/"SimHei"; the t2c/t2w/t2g dictionaries target substrings for per-word color, weight and gradient — the 3b1b look. MarkupText() accepts Pango markup for rich styling inside one string. Paragraph() handles multi-line blocks with line spacing and per-line alignment. MathTex() is a separate LaTeX channel for formulas (see our Chinese LaTeX chapter). This guide covers font_size semantics (72 units ≈ cap height, not points), positioning and alignment (arrange, align_to, to_edge with buff), typewriter and AddCorrectionLetter-style reveals, mixing Text and MathTex on one line via VGroup, line wrapping long Chinese strings, and the font fallback pitfalls that produce tofu boxes on fresh systems.

三层文字系统,各管一段

类通道用途
TextPango 系统字体正文、标题、中文
MarkupTextPango + 标签一段话里混排样式
ParagraphPango 多行成段文字
MathTex / TexLaTeX公式(见中文 LaTeX 章)

Text:日常主力

from manim import *

class TextDemo(Scene):
    def construct(self):
        t = Text(
            "Manim 让数学动起来",
            font="Microsoft YaHei",     # 中文必指定字体
            font_size=48,
            t2c={"Manim": BLUE, "数学": YELLOW},   # 分词着色
            t2w={"动起来": BOLD},                  # 分词加粗
            gradient=("WHITE", "#8cc0ff"),         # 整体渐变
        )
        self.play(Write(t))
        self.wait()

t2c/t2w 的键是子串,会匹配字符串里所有出现位置——适合把关键词高亮成 3b1b 那种"一句话里两种颜色"的效果。

font_size 的真实含义

Manim 的 font_size 单位不是磅,是"画面单位"(默认高度约 8 个单位的屏幕上,48 号字大约占 0.7 个单位高)。常用参考:

  • 正文 28~32 · 小标题 40 · 大标题 56+ · 水印角标 20
  • 想让所有文字统一比例,可以定义项目级常量 TITLE=52, BODY=30

MarkupText:一段话里的富文本

m = MarkupText(
    '重点: 加粗、斜体、'
    '变色、'
    '变大 和 变小',
    font="Microsoft YaHei")
self.play(Write(m))

Paragraph:成段文字与行距

p = Paragraph(
    "第一行:介绍概念。",
    "第二行:给出公式。",
    "第三行:展示动画。",
    font="Microsoft YaHei", font_size=30,
    line_spacing=1.4,          # 行距倍数
    alignment="left",          # left/center/right
)
p.to_edge(LEFT, buff=1)
self.play(AddTextLetterByLetter(p[0]))   # 逐字打出第一行

长中文自动换行

Text 不会自动换行,长句要自己切:

def wrap_cn(s, n=18):
    return "\n".join(s[i:i+n] for i in range(0, len(s), n))

t = Text(wrap_cn("这是一段很长的中文说明文字,需要在画面里优雅地折成多行。"),
         font="Microsoft YaHei", font_size=30, line_spacing=1.3)

中英 + 公式混排一行

cn = Text("定义域为", font="Microsoft YaHei", font_size=32)
math = MathTex("[0, +\infty)", font_size=48)
line = VGroup(cn, math).arrange(RIGHT, buff=0.2)
line.to_edge(UP)
self.play(FadeIn(cn), Write(math))

公式与中文基线对齐用 arrange 自动完成;手动微调 math.align_to(cn, DOWN)(向下对齐基线观感最稳)。

对齐与摆放工具箱

  • arrange(DOWN, aligned_on=LEFT, buff=0.3) — 多行左对齐堆叠(列表/推导标准写法)
  • to_edge(UP, buff=0.4) — 顶到边缘留白
  • align_to(other, UP) — 与别的对象顶端对齐
  • SurroundingRectangle(text, buff=0.15) — 给重点文字加框

排错速查

  • 方块豆腐:字体名不存在或未安装,见中文渲染章的字体清单。
  • t2c 不生效:键里带空格/标点要与原文完全一致,区分大小写。
  • 逐字动画太慢:Write 的 run_time 控制整体时长;AddTextLetterByLetter(time_per_char=0.05) 是打字机节奏。