边学边做Manim的函数绘制方法

Manim中,axes.plot()Axes 类 的一个方法,用于绘制函数曲线。它根据给定的函数和定义域生成对应的点,并将它们连接成平滑的曲线。


1、基本语法

1
2
3
4
5
6
axes.plot(
function: Callable[[float], float],
x_range: Sequence[float] = None,
use_smoothing: bool = True,
**kwargs
) -> ParametricFunction
  1. function: 一个以 x 为自变量、返回 y 值的函数
  2. x_range: x 的取值范围,格式为 [x_min, x_max, step](可选,默认使用坐标轴范围)
  3. use_smoothing: 是否平滑连接点(默认为 True)
  4. kwargs: 其他图形属性参数(如颜色、线宽等)

2、基础示例

2.1. 绘制简单函数

先创建坐标系,然后绘制一个sin(x)的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from manim import *

class PlotExample(Scene):
def construct(self):
# 创建坐标系
axes = Axes(
x_range=[-3, 3, 1],
y_range=[-2, 2, 1],
x_length=6,
y_length=4
)
self.play(Create(axes))
self.wait()

# 绘制正弦函数
sin_graph = axes.plot(
lambda x: np.sin(x), # 函数
x_range=[-3, 3], # x范围
color=BLUE
)

self.play(Create(sin_graph))
self.wait()

2.2. 多个函数叠加

先绘制坐标系,然后绘制二次函数图像,在绘制一次函数的图像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MultiplePlots(Scene):
def construct(self):
axes = Axes(x_range=[-2, 2], y_range=[-1, 3])

# 绘制二次函数
parabola = axes.plot(
lambda x: x**2,
color=RED,
stroke_width=3
)

# 绘制直线
line = axes.plot(
lambda x: x + 1,
color=GREEN
)

self.add(axes, parabola, line)

3、常用参数详解

3.1. x_range 参数

1
2
3
4
5
6
# 指定详细的采样范围
graph = axes.plot(
lambda x: np.cos(x),
x_range=[-PI, PI, 0.1], # 从 -π 到 π,步长 0.1
color=PURPLE
)

3.2. 禁用平滑

1
2
3
4
5
6
# 折线效果
jagged = axes.plot(
lambda x: abs(x),
use_smoothing=False, # 不平滑
color=ORANGE
)

Manim数学动画库中,abs(x) 表示绝对值函数,即 |x|。在这里是绘制一个一次函数y=x的绝对值函数,数学上abs(x) 返回 x 的非负值

  1. x ≥ 0 时,abs(x) = x
  2. x < 0 时,abs(x) = -x

有意思的是,use_smoothing=False也就是不平滑的时候,比平滑的效果更好。

3.3. 样式定制

1
2
3
4
5
6
7
8
9
styled_graph = axes.plot(
lambda x: 0.5 * x**3 - x,
color=YELLOW,
stroke_width=4,
stroke_opacity=0.8,
stroke_color=RED, # 描边颜色
fill_color=BLUE, # 填充颜色(需要封闭图形)
fill_opacity=0.2
)

这次的效果有点儿莫名其妙,给大家发一个我的视频


4、高级用法

4.1. 动态绘制(动画)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class AnimatedPlot(Scene):
def construct(self):
axes = Axes(x_range=[-3, 3], y_range=[-2, 2])

def func(x):
return np.sin(x) * np.exp(-0.2*x)

graph = axes.plot(func, color=TEAL)

# 创建绘制动画
draw_anim = Create(graph, run_time=3, rate_func=linear)

self.add(axes)
self.play(draw_anim)

4.2. 获取点坐标

1
2
3
4
5
6
7
8
9
10
11
12
class GetPoints(Scene):
def construct(self):
axes = Axes(x_range=[0, 4], y_range=[0, 16])
graph = axes.plot(lambda x: x**2)

# 获取 x=2 处的点
point = axes.c2p(2, 4) # 坐标轴坐标转屏幕坐标
dot = Dot(point, color=RED)

label = axes.get_graph_label(graph, "y=x^2", x_val=2)

self.add(axes, graph, dot, label)

4.3. 参数方程(间接实现)

1
2
3
4
5
6
7
8
9
10
11
12
class ParametricPlot(Scene):
def construct(self):
axes = Axes()

# 使用 ParametricFunction 绘制参数方程
param_func = axes.plot_parametric_curve(
lambda t: np.array([np.cos(3*t), np.sin(2*t), 0]),
t_range=[0, TAU],
color=MAROON
)

self.add(axes, param_func)

5、实用技巧

5.1. 自定义采样精度

1
2
3
4
5
6
# 通过调整 x_range 的步长控制精度
high_precision = axes.plot(
lambda x: np.sin(1/x),
x_range=[0.01, 1, 0.001], # 小步长提高精度
color=BLUE
)

5.2. 分段函数

1
2
3
4
5
6
7
8
9
def piecewise(x):
if x < 0:
return -x
else:
return x**2

# 分段绘制
left = axes.plot(lambda x: -x, x_range=[-3, 0])
right = axes.plot(lambda x: x**2, x_range=[0, 3])

5.3. 与坐标轴交互

1
2
3
4
5
6
7
8
9
10
11
12
class InteractivePlot(Scene):
def construct(self):
axes = Axes()
graph = axes.plot(lambda x: np.exp(-x) * np.cos(x))

# 添加坐标轴标签
axes_labels = axes.get_axis_labels(x_label="x", y_label="f(x)")

# 添加曲线标签
graph_label = axes.get_graph_label(graph, label="e^{-x}cos(x)")

self.add(axes, axes_labels, graph, graph_label)

6、常见问题

6.1. 函数值超出范围

1
2
3
# 自动裁剪,不会报错但可能不显示
graph = axes.plot(lambda x: 10*x, x_range=[-1, 1])
# 建议调整 y_range 或函数缩放

6.2. 性能优化

1
2
3
4
5
6
# 复杂函数减少采样点
fast_plot = axes.plot(
lambda x: np.sin(x**2),
x_range=[-4, 4, 0.2], # 增大步长
use_smoothing=True
)

6.3. 颜色渐变

1
2
3
4
5
6
from manim.utils.color import interpolate_color

graph = axes.plot(
lambda x: np.sin(x),
color=interpolate_color(BLUE, GREEN, x/4) # 动态颜色
)

今天的经验就汇总到这里,关键是注意函数的画法,也就是axes.plot()和lambda的搭配使用,注意参数问题。