Manim 的 Axes 和 NumberPlane 有什么区别?范围、刻度怎么配
2026 年 11 月 8 日 · 极坐标⋅XYZ
Manim 的 Axes 和 NumberPlane 有什么区别?范围、刻度怎么配
NumberPlane 就是 Axes 加上一层背景网格:两者都是由 x、y 两根数轴拼成的二维坐标系,c2p、plot 这些方法用法完全一样,区别只在 NumberPlane 多画了网格线。范围和刻度由 x_range、y_range 配置,每个都是 [起点, 终点, 步长]:起点和终点决定这根轴覆盖的数学范围,步长决定刻度(NumberPlane 里同时是网格)的间隔;x_length、y_length 则决定它在屏幕上占多大。
Manim 是 3Blue1Brown 开源的数学动画引擎,画面里的坐标轴、曲线、公式都是 Python 对象,由你用代码来描述。现在通用的是社区维护的 Manim Community。本文代码按 0.21.0 实测(极坐标⋅XYZ 工作区与教程用的就是这一版),PyPI 上 0.22.0 已于 2026 年 10 月 8 日发布。还不熟悉的话,可以先翻一下这篇介绍;想把画函数这一块系统过一遍,极坐标⋅XYZ 的教程是按 0.21.0 做的 2026 年最新中文版,坐标系和函数作图有专门一章。
下面的完整代码都能在极坐标⋅XYZ 的工作区里直接运行,工作区装的是同一版本,不用自己装环境。
最小可运行的例子:同样的范围,并排放一个 Axes 和一个 NumberPlane
两个坐标系用一模一样的 x_range、y_range、x_length、y_length,左边是 Axes,右边是 NumberPlane,再各画一条 y = 0.4x² 的抛物线。曲线的写法一个字都没差:
from manim import *
class AxesVsPlane(Scene):
def construct(self):
cfg = dict(
x_range=[-4, 4, 1],
y_range=[-3, 3, 1],
x_length=5.6,
y_length=4.2,
)
axes = Axes(**cfg, axis_config={"include_numbers": True}).shift(LEFT * 3.4)
plane = NumberPlane(**cfg).shift(RIGHT * 3.4)
t1 = Text("Axes", font_size=32).next_to(axes, UP)
t2 = Text("NumberPlane", font_size=32).next_to(plane, UP)
curve1 = axes.plot(lambda x: 0.4 * x**2, color=YELLOW)
curve2 = plane.plot(lambda x: 0.4 * x**2, color=YELLOW)
self.play(Create(axes), Create(plane), FadeIn(t1), FadeIn(t2))
self.play(Create(curve1), Create(curve2))
self.wait()
左边是两根带数字刻度的轴,右边是一整片网格。其余完全相同:同一条曲线、同一个范围。NumberPlane 是 Axes 的子类,所以 Axes 能做的事它都能做。
为什么是这样
差别在哪:多一层网格,以及默认值
课程里对 NumberPlane 的定义很直接:NumberPlane = Axes + 背景网格。网格的样子用 background_line_style 调:
plane = NumberPlane(
x_range=[-4, 4, 1],
y_range=[-3, 3, 1],
background_line_style={
"stroke_color": BLUE_D,
"stroke_width": 1,
"stroke_opacity": 0.5,
},
)
网格线的间隔就是 x_range、y_range 的步长,所以步长既管刻度也管网格。
另一个容易忽略的差别是默认值:在默认画布下,NumberPlane() 不传参数会铺满整个画面,Axes() 不传参数则是一对默认长度的轴(12×6),不一定铺满。改过画布配置的话,铺满的范围在 import 时就定下了,细节见画布尺寸和像素换算。需要精确控制,两个都显式写出范围和长度,最省心。
x_range、y_range 和 x_length、y_length:范围和大小是两回事
| 参数 | 管什么 | 单位 |
|---|---|---|
x_range=[起点, 终点, 步长] |
x 轴覆盖的数学范围,刻度间隔 | 数学坐标 |
y_range=[起点, 终点, 步长] |
y 轴同理 | 数学坐标 |
x_length、y_length |
这根轴在屏幕上多长 | Manim 的单位长度 |
axes = Axes(
x_range=[-4, 4, 1], # 起点, 终点, 步长
y_range=[-3, 3, 1],
x_length=8, # 屏幕上的宽
y_length=6, # 屏幕上的高
axis_config={"include_numbers": True},
)
这里 x 范围是 8 个数学单位、屏幕上长 8,每格恰好是 1 个屏幕单位。把 x_length 改成 4,范围不变,图就缩成一半宽,坐标值依然是 -4 到 4。反过来,范围改了、长度不变,同样的屏幕宽度就装更多数学坐标。想让数学坐标和屏幕坐标一比一,就让长度等于范围的跨度。
刻度怎么配
刻度由三处共同决定。
1. 步长,x_range 的第三个数。 [0, 10, 2] 是 0、2、4、6、8、10 各一个刻度。步长不一定是整数,[-1, 1, 0.5] 就是每 0.5 一格。
2. 刻度下面要不要标数字。 axis_config={"include_numbers": True} 对两根轴一起生效,想只给一根轴标数字,用 x_axis_config、y_axis_config 分别写。
3. 数字的格式。 把小数位数放进对应轴的配置:
from manim import *
class TickConfig(Scene):
def construct(self):
axes = Axes(
x_range=[0, 10, 2],
y_range=[-1, 1, 0.5],
x_length=9,
y_length=4,
x_axis_config={"include_numbers": True},
y_axis_config={
"include_numbers": True,
"decimal_number_config": {"num_decimal_places": 1},
},
tips=False,
)
graph = axes.plot(lambda x: np.sin(x), x_range=[0, 10, 0.05], color=YELLOW)
self.play(Create(axes))
self.play(Create(graph), run_time=2)
self.wait()
x 轴每 2 一个刻度、标整数;y 轴每 0.5 一个刻度,数字固定一位小数。tips=False 是去掉轴末端的箭头。
注意代码里 axes.plot 的 x_range=[0, 10, 0.05] 和坐标系自己的 x_range 不是一回事:这里的第三个数是采样步长。课程里专门讲过,曲线其实是由一段段小线段近似出来的,步长太大曲线会变成明显的折线,所以要取得小一些。
坐标怎么换算
课程里把 Axes 概括为:两根 NumberLine 组成的二维坐标系。每根轴本身就是一根数轴,所以 x_range、include_numbers 这些参数和单独用 NumberLine 时是同一套。
坐标系还牵涉两套参考系:points 是屏幕的绝对坐标,也就是相机真正看到的位置;coords 是坐标系自己的坐标,也就是数学里的 x、y,会随 x_range 和摆放位置而变。c2p(coords_to_point)把坐标换成屏幕上的点,p2c(point_to_coords)反过来。后面画函数、标点、画面积,都靠 axes.c2p 把数学坐标摆到屏幕上。NumberPlane 继承了这些,所以不管选哪个,换算的写法都不用改。
p = axes.c2p(2, 1) # 数学坐标 (2, 1) -> 屏幕上的点
x, y = axes.p2c(dot.get_center()) # 屏幕上的点 -> 数学坐标
常见写错的地方
把 x_range 的第三个数当成长度
axes = Axes(x_range=[-4, 4, 8]) # 想让 x 轴长 8
第三个数是步长,上面这样写,整根轴只有两个刻度。要让它在屏幕上变宽,改的是 x_length。
只写了范围,以为图会自动铺满
Axes 的屏幕大小由 x_length、y_length 决定,不是由范围决定。范围改得很大(比如 [-100, 100, 10]),轴的屏幕长度不变,每个数学单位就变得很细。要么同时调长度,要么接受缩小后的样子。
标点时忘了 c2p
自己用 Dot 标点时,直接写 Dot([2, 1, 0]),点会落在屏幕坐标 (2, 1),而不是坐标系里的 (2, 1)。两者只有在坐标系正好以屏幕原点为中心、长度等于范围时才碰巧一致。要用 axes.c2p(2, 1) 换算:
dot = Dot(axes.c2p(2, 1), color=YELLOW)
常见追问(FAQ)
Q:我只想要网格,不要刻度数字,用哪个?
A:用 NumberPlane,它默认就只有网格和轴线,没有数字。要数字,再通过 axis_config 打开。
Q:画函数图像,Axes 和 NumberPlane 选哪个?
A:都行,plot、c2p 的用法一样。想要干净的图用 Axes,想要方格纸的感觉、方便读数时用 NumberPlane。
Q:x_range 的起点必须小于终点吗?
A:正常写法是起点小于终点、步长为正。起点、终点不必关于 0 对称,[0, 10, 2] 完全可以。
Q:怎么拿到某个数学坐标在屏幕上的位置?
A:axes.c2p(x, y)。反过来用 axes.p2c(点)。
Q:NumberPlane 的网格线颜色、粗细怎么改?
A:通过 background_line_style,设置 stroke_color、stroke_width、stroke_opacity。
这个知识点在教程《坐标系与函数作图》里有配套视频和可改的代码,里面按「数轴 → Axes → plot」的顺序一步步搭起来;想直接动手,打开工作区。
来源:极坐标⋅XYZ · jizuobiao.xyz · 更新于 2026-11-08 · 基于 Manim Community 0.21.0