ManimGL 常量体系详解:constants.py 中的画幅、Buff、坐标向量与颜色配置
ManimGL(包名 manimgl)的场景代码中反复出现的 UP、BLUE、TAU、LARGE_BUFF 等符号,全部定义在 constants.py 中,而其中相当一部分常量的取值并不是硬编码的,而是由 default_config.yml 及用户自定义配置驱动生成。本文围绕官方文档 constants.rst 的脉络,逐组讲清这些常量的定义、来源与底层用途,帮助你在编写动画场景和定制渲染参数时准确使用它们。
一、常量从哪里来:配置驱动的生成机制
constants.py 顶部有一行关键导入(见 constants.py):
# See manimlib/default_config.yml
from manimlib.config import manim_config
也就是说,常量模块在导入时会直接读取全局配置对象 manim_config。该对象的构建过程在 config.py 的 initialize_manim_config() 中完成,合并顺序为:
manimlib/default_config.yml(仓库内置默认值);- 当前工作目录下的
custom_config.yml(若存在); - 通过
--config_file /path/to/xxx.yml显式传入的配置文件; - 命令行参数(分辨率、帧率、背景色等)的最高优先级覆盖。
这一链路意味着:修改 sizes、camera、colors 等配置节,就能在不改任何 Python 代码的情况下改变本文后续所有“可变常量”的实际取值。default_config.yml 文件开头的注释也说明了这一用法:在项目目录放置 custom_config.yml,或用 --config_file 指定任意位置的文件。
二、画幅与像素形状(Frame and pixel shape)
文档指出这组值由配置中的 camera 节决定。对照源码 constants.py:
DEFAULT_RESOLUTION: tuple[int, int] = manim_config.camera.resolution
DEFAULT_PIXEL_WIDTH: int = DEFAULT_RESOLUTION[0]
DEFAULT_PIXEL_HEIGHT: int = DEFAULT_RESOLUTION[1]
# Sizes relevant to default camera frame
ASPECT_RATIO: float = DEFAULT_PIXEL_WIDTH / DEFAULT_PIXEL_HEIGHT
FRAME_HEIGHT: float = manim_config.sizes.frame_height
FRAME_WIDTH: float = FRAME_HEIGHT * ASPECT_RATIO
FRAME_SHAPE: tuple[float, float] = (FRAME_WIDTH, FRAME_HEIGHT)
FRAME_Y_RADIUS: float = FRAME_HEIGHT / 2
FRAME_X_RADIUS: float = FRAME_WIDTH / 2
各常量的含义与推导关系:
| 常量 | 默认值(以默认配置推算) | 来源 |
|---|---|---|
DEFAULT_PIXEL_WIDTH / DEFAULT_PIXEL_HEIGHT |
1920 / 1080 | default_config.yml 中 camera.resolution: (1920, 1080) |
ASPECT_RATIO |
1920/1080 ≈ 16/9 | DEFAULT_PIXEL_WIDTH / DEFAULT_PIXEL_HEIGHT |
FRAME_HEIGHT |
8.0 | default_config.yml 中 sizes.frame_height: 8.0 |
FRAME_WIDTH |
8.0 × 16/9 ≈ 14.22 | FRAME_HEIGHT * ASPECT_RATIO |
FRAME_Y_RADIUS / FRAME_X_RADIUS |
4.0 / ≈7.11 | 画幅高度、宽度的一半 |
两点值得注意:
- 场景坐标系高度固定为 8 个 manim 单位(由
frame_height决定),宽度则随分辨率宽高比缩放。这就是为什么to_edge(RIGHT)、FRAME_X_RADIUS等量会随-l/-m/--uhd切换而变化——这些参数通过 config.py 的get_resolution_from_args()改写camera.resolution,对应 default_config.yml 中resolution_options的low (854,480)、med (1280,720)、high (1920,1080)、4k (3840,2160)。 - 文档同时列出了
DEFAULT_FPS。从当前源码结构看,constants.py已不再单独导出DEFAULT_FPS;帧率直接走manim_config.camera.fps(默认 30,见 default_config.yml),并作为 camera.py 中Camera(fps: int = 30)的默认参数使用,--fps命令行参数可在运行时覆盖(见 config.py)。
这些画幅常量在渲染管线中是真实生效的:Camera.refresh_uniforms() 把 frame_rescale_factors=(2.0 / FRAME_WIDTH, 2.0 / FRAME_HEIGHT, ...) 写入共享 uniform 块(见 camera.py),着色器据此把场景坐标映射到标准化设备坐标。
三、Buff 间距常量
文档中这组值由配置的 sizes 节决定。源码见 constants.py,默认取值来自 default_config.yml:
SMALL_BUFF: float = manim_config.sizes.small_buff # 0.1
MED_SMALL_BUFF: float = manim_config.sizes.med_small_buff # 0.25
MED_LARGE_BUFF: float = manim_config.sizes.med_large_buff # 0.5
LARGE_BUFF: float = manim_config.sizes.large_buff # 1.0
DEFAULT_MOBJECT_TO_EDGE_BUFF: float = manim_config.sizes.default_mobject_to_edge_buff # 0.5
DEFAULT_MOBJECT_TO_MOBJECT_BUFF: float = manim_config.sizes.default_mobject_to_mobject_buff # 0.25
default_config.yml 对它们有明确注释:“determine the constants SMALL_BUFF, MED_SMALL_BUFF, etc., useful for nudging things around and having default spacing values”。它们的实际消费点在 mobject.py:
to_corner()/to_edge()的buff参数默认取DEFAULT_MOBJECT_TO_EDGE_BUFF;next_to()的buff参数默认取DEFAULT_MOBJECT_TO_MOBJECT_BUFF;align_on_border()在计算target_point = np.sign(direction) * (FRAME_X_RADIUS, FRAME_Y_RADIUS, 0)时还同时依赖第二节中的画幅半径常量。
官方示例 example_scenes.py 中 lines.arrange(DOWN, buff=LARGE_BUFF) 就是典型用法:用命名常量代替魔法数字,让间距意图一目了然。
四、三维坐标与方向向量
文档强调 Manim 使用三维坐标、ndarray 类型。源码中这组向量带 Vect3 类型标注(该标注定义于 typing.py,实际路径为 manimlib/typing.py,是 3 维 np.ndarray 的可读别名),见 constants.py:
# Standard vectors
ORIGIN = np.array([0., 0., 0.])
UP = np.array([0., 1., 0.])
DOWN = np.array([0., -1., 0.])
RIGHT = np.array([1., 0., 0.])
LEFT = np.array([-1., 0., 0.])
IN = np.array([0., 0., -1.])
OUT = np.array([0., 0., 1.])
X_AXIS = np.array([1., 0., 0.])
Y_AXIS = np.array([0., 1., 0.])
Z_AXIS = np.array([0., 0., 1.])
# Useful abbreviations for diagonals
UL = UP + LEFT
UR = UP + RIGHT
DL = DOWN + LEFT
DR = DOWN + RIGHT
TOP = FRAME_Y_RADIUS * UP
BOTTOM = FRAME_Y_RADIUS * DOWN
LEFT_SIDE = FRAME_X_RADIUS * LEFT
RIGHT_SIDE = FRAME_X_RADIUS * RIGHT
需要区分两层语义:
UP、RIGHT、UL等是单位方向向量,to_edge(UP)、arrange(RIGHT)、shift(2 * RIGHT)接受的都是方向;TOP、BOTTOM、LEFT_SIDE、RIGHT_SIDE是帧边界的实际位置点,把单位向量放大了FRAME_Y_RADIUS/FRAME_X_RADIUS倍,其数值随分辨率宽高比联动变化。
方向向量在 mobject.py 的 shift_onto_screen() 中被用于逐侧判断 mobject 是否越界(for vect in UP, DOWN, LEFT, RIGHT:),可见它们是布局 API 的基础设施,而非仅是语法糖。
五、数学(角度)常量
文档给出 PI、TAU、DEG 三个常量,源码见 constants.py,还有两个文档未展开的同源常量:
PI: float = np.pi
TAU: float = 2 * PI
DEG: float = TAU / 360
DEGREES = DEG # Many older animations use the full name
# Nice to have a constant for readability
# when juxtaposed with expressions like 30 * DEG
RADIANS: float = 1
TAU表示整圆角(2π),DEG把一个度数换算成弧度,二者让Rotate(obj, angle=90 * DEG)这类写法直接可读;- 源码注释特别提到
RADIANS = 1的存在是为了配合30 * DEG这类表达式的可读性;DEGREES则是为了兼容使用全名的旧动画代码。
实际用法可参考 example_scenes.py 中 path_arc=90 * DEG、path_arc=-30 * DEG,以及 example_scenes.py 中 set_height(TAU - MED_SMALL_BUFF) 把角度常量与 buff 常量混用的例子。
六、文本样式常量
constants.py 定义了四个字符串常量:
# Related to Text
NORMAL: str = "NORMAL"
ITALIC: str = "ITALIC"
OBLIQUE: str = "OBLIQUE"
BOLD: str = "BOLD"
源码注释标明它们“Related to Text”,即在 text_mobject.py 的 Text mobject 中表示字体样式(字重/斜体形态)。用常量而非裸字符串传样式,可以避免拼写错误并让意图显式化。
七、颜色常量体系
文档指出颜色常量由配置的 colors 节决定,并附有一张默认调色板预览(BLUE/TEAL/GREEN/YELLOW/GOLD/RED/MAROON/PURPLE/GREY 各 5 档,外加 WHITE、BLACK 等)。源码实现分三层:
1. 逐色从配置读取。 constants.py 中每个颜色都是 manim_config.colors.<name>,默认十六进制值定义在 default_config.yml:
colors:
blue_e: "#1C758A"
blue_d: "#29ABCA"
blue_c: "#58C4DD"
blue_b: "#9CDCEB"
blue_a: "#C7E9F1"
# ... teal/green/yellow/gold/red/maroon/purple/grey 同样各 5 档 ...
white: "#FFFFFF"
black: "#000000"
grey_brown: "#736357"
dark_brown: "#8B4513"
light_brown: "#CD853F"
pink: "#D147BD"
light_pink: "#DC75CD"
green_screen: "#00FF00"
orange: "#FF862F"
pure_red: "#FF0000"
pure_green: "#00FF00"
pure_blue: "#0000FF"
后缀约定与调色板一致:_e 最深、_a 最浅,_c 为中间档。
2. 缩写名与派生列表。 源码在文档基础上还有几处补充(见 constants.py):
MANIM_COLORS: List[ManimColor] = list(manim_config.colors.values())
# Abbreviated names for the "median" colors
BLUE = BLUE_C
TEAL = TEAL_C
GREEN = GREEN_C
YELLOW = YELLOW_C
GOLD = GOLD_C
RED = RED_C
MAROON = MAROON_C
PURPLE = PURPLE_C
GREY = GREY_C
COLORMAP_3B1B: List[ManimColor] = [BLUE_E, GREEN, YELLOW, RED]
MANIM_COLORS 汇总了配置中全部颜色;BLUE 等无后缀名一律指向中间档;COLORMAP_3B1B 是现成的四色调色板。
3. mobject 默认颜色。 一组默认色让文本、轴线、描边/填充在未显式指定颜色时获得一致外观,且同样可配置:
# Default mobject colors should be configurable just like background color
DEFAULT_MOBJECT_COLOR: ManimColor = manim_config.mobject.default_mobject_color or WHITE
DEFAULT_LIGHT_COLOR: ManimColor = manim_config.mobject.default_light_color or GREY_B
DEFAULT_VMOBJECT_STROKE_COLOR: ManimColor = manim_config.vmobject.default_stroke_color or GREY_A
DEFAULT_VMOBJECT_FILL_COLOR: ManimColor = manim_config.vmobject.default_fill_color or GREY_C
对应的配置项在 default_config.yml:vmobject.default_stroke_color: "#DDDDDD"(即 GREY_A)、default_fill_color: "#888888"(即 GREY_C),mobject.default_mobject_color: "#FFFFFF"(WHITE)、default_light_color: "#BBBBBB"(GREY_B)。
在场景代码中,这套颜色被高频使用,例如 example_scenes.py 的 set_submobject_colors_by_gradient(BLUE, GREEN) 与 example_scenes.py 的 set_color(RED)。
八、实操:用 custom_config.yml 调整这些常量
由于第二、三、七节的常量都是配置驱动的,一次典型的定制如下(示例为说明用途,文件应放在你自己的项目目录中):
# custom_config.yml(放在运行 manim 的目录,或用 --config_file 指定)
camera:
resolution: (1280, 720) # ASPECT_RATIO 变为 16/9,FRAME_WIDTH 随之一致
background_color: "#1a1a2e"
sizes:
frame_height: 8.0 # FRAME_HEIGHT;改为其他值可整体缩放场景坐标系
small_buff: 0.15 # SMALL_BUFF
large_buff: 1.25 # LARGE_BUFF
colors:
blue_c: "#7EC8E3" # 覆盖 BLUE 的实际取值
red_a: "#F9B8BA"
vmobject:
default_stroke_color: "#999999" # DEFAULT_VMOBJECT_STROKE_COLOR
运行方式:在场景文件所在目录直接执行(自动拾取 custom_config.yml),或显式指定:
python -m manimlib my_scene.py MyScene --config_file /path/to/custom_config.yml
命令行仍保有最高优先级,如 --fps 60、-r 1920x1080、-c "#222222"(背景色)会在配置合并后覆盖对应值(见 config.py 的 update_camera_config())。
九、证据与延伸阅读
本文涉及的仓库内路径,便于逐条核验:
- 常量定义:manimlib/constants.py
- 默认配置:manimlib/default_config.yml
- 配置合并与 CLI 覆盖:manimlib/config.py
- 画幅常量在渲染 uniform 中的消费:manimlib/camera/camera.py
- buff 常量在布局 API 中的消费:manimlib/mobject/mobject.py
Vect3类型标注:manimlib/typing.py- 用法示例:example_scenes.py
- 原始文档:docs/source/documentation/constants.rst
需要注意的是适用前提:本文所有默认值均以当前仓库 default_config.yml 的内置配置为准,且针对的是 GPU 渲染版 ManimGL(PyPI 包名 manimgl);若你通过 custom_config.yml 覆盖了 sizes、camera 或 colors 节,文中对应“默认值”即随之改变。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00