首页 / 文档中心 / 进阶

Manim 坐标系与函数图像:Axes、NumberPlane 完全指南

发布于 2026-11-02 · 进阶系列 · 约 5 分钟读完 · 中文正文 + English TL;DR
▶ 渲染效果实录(manim 渲染输出,代码见正文,可直接复现)
English TL;DR

Everything about plotting in Manim CE: build a coordinate system with Axes (x_range, y_range, lengths, per-axis configs), draw curves with axes.plot(), decorate with add_coordinates() and get_graph_label, fill areas with get_area(), and visualize integration with get_riemann_rectangles(). NumberPlane gives the faded grid look of 3Blue1Brown videos. Parametric curves use plot_parametric_curve, polar graphs plot_polar_graph, and ImplicitFunction draws level sets like circles without solving for y. The key mental model: axes are Mobjects, and coords_to_point / point_to_coords convert between math space and screen space — every annotation (dots, dashed lines, labels) should be placed through this bridge. Includes a runnable tour scene with a sine curve, tangent dot, and Riemann rectangles.

核心心智模型:数学坐标 → 屏幕坐标

Manim 画面本身用"屏幕坐标”(中心是原点,左右各约 7 个单位、上下各约 4 个单位)。Axes 负责在屏幕上开一个窗口,把数学坐标映射进去。所有标注点都必须先过 axes.coords_to_point(x, y)(简写 axes.c2p)这座桥:

axes = Axes(x_range=[-3, 3, 1], y_range=[-2, 2, 1], x_length=9, y_length=5)
dot = Dot(axes.c2p(2, 1))          # 数学点 (2,1) 处画点, 而不是屏幕 (2,1)

一、创建坐标系并画第一条曲线

from manim import *

class PlotTour(Scene):
    def construct(self):
        axes = Axes(
            x_range=[-4, 4, 1], y_range=[-2, 2, 1],
            x_length=9, y_length=4.5,
            x_axis_config={"include_numbers": True},
            y_axis_config={"include_numbers": True},
            axis_config={"color": GREY_B, "stroke_width": 2},
        )
        curve = axes.plot(lambda x: np.sin(x), x_range=[-4, 4], color=BLUE)
        label = axes.get_graph_label(curve, "sin(x)", x_val=3, direction=UR)

        self.play(Create(axes), run_time=2)
        self.play(Create(curve), Write(label))
        self.wait()
  • x_range=[起, 止, 步长] — 步长控制刻度密度
  • x_axis_config / y_axis_config — 单独配置两根轴(0.18+ 语法,旧的 axis_config 已弃用)
  • include_numbers — 轴上标数字;axes.add_coordinates() 是等效的链式写法

二、面积与积分可视化

微积分教学是 Manim 的主场,两个 API 覆盖 90% 场景:

curve = axes.plot(lambda x: np.sin(x), x_range=[0, np.pi], color=BLUE)

# 1) 填充面积
area = axes.get_area(curve, x_range=[0, np.pi], color=TEAL, opacity=0.5)

# 2) 黎曼矩形逼近
rects = axes.get_riemann_rectangles(
    curve, x_range=[0, np.pi], dx=0.4, input_sample_type="left",
    color=[TEAL, BLUE_D], stroke_width=0.5)

self.play(Create(curve))
self.play(DrawBorderThenFill(area))
self.play(FadeOut(area))
self.play(Create(rects))
self.wait()

配合 ValueTracker 让 dx 动起来(矩形越来越细逼近曲边梯形),是复刻系列第一期的核心手法。

三、曲线上的动点与辅助线

t = ValueTracker(0)
dot = always_redraw(
    lambda: Dot(axes.c2p(t.get_value(), np.sin(t.get_value())),
                color=YELLOW))
vline = always_redraw(
    lambda: DashedLine(
        axes.c2p(t.get_value(), 0),
        axes.c2p(t.get_value(), np.sin(t.get_value())),
        stroke_opacity=0.6))
self.add(axes, curve, vline, dot)
self.play(t.animate.set_value(6), run_time=4, rate_func=linear)

always_redraw 每帧重建对象,是"跟随"效果的标准解,原理见Updater 与 ValueTracker。

四、NumberPlane:3b1b 风格的网格

plane = NumberPlane(
    x_range=[-6, 6, 1], y_range=[-4, 4, 1],
    background_line_style={"stroke_color": BLUE_D, "stroke_width": 1.5},
    faded_line_ratio=3)   # 每 3 条细线夹 1 条粗线

NumberPlane 继承自 Axes,坐标函数照用。画变换动画(网格扭曲、矩阵作用)时它是标配,见线性变换复刻。

五、参数方程、极坐标与隐函数

# 参数方程: 心形线
polar = axes.plot_polar_graph(
    lambda t: 2 + np.cos(t), t_range=[0, 2 * np.pi], color=PINK)

# 参数曲线
epi = axes.plot_parametric_curve(
    lambda t: np.array([np.cos(3*t), np.sin(5*t), 0]),
    t_range=[0, 2 * np.pi], color=TEAL)

# 隐函数: 不用解 y 也能画圆
circle = ImplicitFunction(
    lambda x, y: x**2 + y**2 - 4, color=YELLOW)

六、常见坑

  • 曲线画到轴外:plot 的 x_range 超过了 Axes 的 x_range 不会被裁剪,会溢出画面,两者要对齐。
  • 函数只接受标量:plot 的 lambda 收到的是单个 x 值,别在里面用 np 数组操作。
  • 标签重叠:get_graph_label 的 direction 参数(UR/UP/RIGHT…)微调位置。