
在Manim库中,FunctionGraph类是一个核心组件,专门用于在坐标系中绘制函数图像。FunctionGraph的主要作用是将数学函数以直观的图形形式展示出来,使得复杂的数学概念更加容易理解。它广泛应用于数学教学、科学演示以及数据可视化等领域。下面是Manim 中的 FunctionGraph 详解
一、概念与适用场景
- FunctionGraph 用于在 Manim 中绘制显式函数 y = f(x) 的二维曲线,要求函数在给定区间内是单值的(每个 x 对应唯一 y)。
- 典型用途:数学教学(展示奇偶性、周期性、渐近线)、物理仿真(位移/速度-时间图)、工程应用(信号波形、控制响应)、算法演示(目标函数、损失函数)。
- 当函数可显式写成 y = f(x) 时优先使用;若方程以 F(x, y) = 0 给出,用 ImplicitFunction;若以参数 r(t) = (x(t), y(t)) 给出,用 **ParametricFunction。
二、常用参数与方法
- 主要参数
- function:可调用对象,形如 Callable[[float], float],如 lambda x: x+5。
- x_range:定义域,支持 [xmin, xmax] 或 [xmin, xmax, step]。
- color:曲线颜色,如 BLUE。
- discontinuities:不连续点列表,如 [0] 用于处理跳跃间断。
- use_smoothing:是否平滑连接采样点,默认 True。
- dt:采样步长(影响平滑度)。
- t_range:高级用法,用于参数化控制。
- 常用方法
- get_function():返回用于绘制的函数对象。
- get_point_from_function(x):给定 x 返回曲线上对应点坐标。
- 坐标系便捷方式
- 在 Axes 上可用 axes.get_graph(func, kwargs)直接生成曲线,并用 axes.get_graph_label(graph, label) 添加标签。
三、快速上手示例
示例 1:
绘制 y = sin(x) 与 y = cos(x)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| from manim import * import numpy as np
class SinCosGraph(Scene): def construct(self): # 创建坐标轴 axes = Axes( x_range=[-3*np.pi, 3*np.pi, np.pi/2], y_range=[-1.5, 1.5, 0.5], axis_config={"color": GREY_A}, x_length=10, y_length=6, ) # 添加坐标轴标签 axes_labels = axes.get_axis_labels( x_label="x", y_label="y" ) # 创建函数图像 sin_func = FunctionGraph( lambda t: np.sin(t), x_range=[-2*np.pi, 2*np.pi], # 必须指定x范围 color=BLUE, ) cos_func = FunctionGraph( lambda t: np.cos(t), x_range=[-2*np.pi, 2*np.pi], # 必须指定x范围 color=RED, ) # 添加图例 sin_label = Text("sin(x)", color=BLUE).next_to(sin_func, UP, buff=0.1) cos_label = Text("cos(x)", color=RED).next_to(cos_func, DOWN, buff=0.1) # 播放动画 self.play(Create(axes), Write(axes_labels)) self.play(Create(sin_func), Write(sin_label)) self.play(Create(cos_func), Write(cos_label)) self.wait()
|
示例 2:
分段与间断(ReLU 与单位阶跃)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| from manim import *
class StepReluGraph(Scene): def construct(self): # 创建坐标系 axes = Axes( x_range=(-1, 5, 1), y_range=(-0.5, 3, 0.5), axis_config={"color": BLUE} ) # 创建 ReLU 函数 relu = axes.plot( lambda x: max(x, 0), x_range=[-1, 5], color=YELLOW, use_smoothing=False ) # 创建阶跃函数 - 手动分段绘制 # 第一部分:x < 3 时 y = 1 step_part1 = axes.plot( lambda x: 1.0, x_range=[-1, 3], color=GREEN, use_smoothing=False ) # 第二部分:x > 3 时 y = 2 step_part2 = axes.plot( lambda x: 2.0, x_range=[3, 5], color=GREEN, use_smoothing=False ) # 在 x=3 处添加垂直线段(可选,表示跳跃) vertical_line = Line( axes.c2p(3, 1), axes.c2p(3, 2), color=GREEN ) # 添加标签 relu_label = axes.get_graph_label(relu, label="ReLU(x) = max(0, x)") step_label = Text("阶跃函数", color=GREEN, font_size=24).next_to(step_part2, UP) # 动画序列 self.play(Create(axes)) self.play(Create(relu)) self.play(Write(relu_label)) self.wait(0.5) self.play(Create(step_part1)) self.play(Create(step_part2)) self.play(Create(vertical_line)) self.play(Write(step_label)) self.wait(2)
|
示例 3:
直接使用 FunctionGraph(不依赖 Axes)
1 2 3 4 5 6 7 8 9
| from manim import * import numpy as np
class DirectFunctionGraph(Scene): def construct(self): graph = FunctionGraph(lambda x: x**2, x_range=[-2, 2], color=BLUE) self.play(Create(graph)) self.wait()
|
示例 4:
动态更新函数形态(Transform 驱动)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from manim import * import numpy as np
class DynamicGraph(Scene): def construct(self): def f(x, t): return np.sin(x + t) g = FunctionGraph(lambda x: f(x, 0), color=TEAL) self.play(Create(g)) self.wait(2) for t in np.linspace(0, 2*np.pi, 30): self.play(Transform(g, FunctionGraph(lambda x: f(x, t), color=TEAL)), run_time=0.1) self.wait()
|
示例 5:
获取曲线上某点坐标
1 2 3 4 5 6 7 8 9 10 11
| from manim import * import numpy as np
class PointOnGraph(Scene): def construct(self): g = FunctionGraph(lambda x: x**2, x_range=[-2, 2], color=BLUE) p = g.get_point_from_function(1.0) # (x, x^2) 在 x=1 处的点 dot = Dot(point=p, color=RED) self.play(Create(g),Create(dot)) self.wait()
|
实例6:
sin函数图像的平移和缩小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| from manim import * import numpy as np
class FunctionGraphExampleattr(Scene):
def construct(self): """函数的平移和缩放"""
# 绘制原始函数图像 func = FunctionGraph( lambda t: np.sin(t), color=BLUE, x_range=[-2*np.pi, 2*np.pi], # 必须指定x范围 )
self.play(Create(func)) self.wait() self.play(func.animate.move_to(UP)) self.wait() self.play(func.animate.scale(0.5)) self.wait()
|
示例7:
创建复合函数的图像并缩小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from manim import * import numpy as np
class FunctionGraphComposite(Scene):
def construct(self):
# 绘制复合函数图像 composite_func = FunctionGraph( lambda t: np.sin(t) + 0.5 * np.sin(7 * t) + (1 / 7) * np.sin(14 * t), color=ORANGE, ) self.play(Create(composite_func)) self.wait() self.play(composite_func.animate.scale(0.5)) self.wait()
|
示例8:
创建一个动态变化的函数
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 * import numpy as np
class FunctionGraphdynamic(Scene): def construct(self): # 定义一个动态变化的函数 def dynamic_func(t, time): return np.sin(t + time)
# 创建一个动态函数图像 dynamic_graph = FunctionGraph( lambda t: dynamic_func(t, 0), color=TEAL, ) self.add(dynamic_graph) # 动态更新函数图像 for time in range(10): new_graph = FunctionGraph( lambda t: dynamic_func(t, time), color=TEAL, ) self.play(Transform(dynamic_graph, new_graph)) self.wait()
|
四、常见问题与实用建议
- 函数必须是显式且单值;多值情形(如圆)应使用 ImplicitFunction,参数曲线使用 ParametricFunction。
- 出现“断点”或“毛刺”时,优先检查定义域与不连续点设置;对分段函数或含绝对值的函数,显式给出 discontinuities 更稳妥。
- 对分段线性(如 ReLU)或需要保留棱角的曲线,设置 use_smoothing=False 以避免曲线被插值“圆滑化”。
- 需要获取曲线上某点坐标进行标注或交互时,使用 get_point_from_function(x);需要在动画中替换函数形态时,用 Transform 在两条 FunctionGraph 间平滑过渡