第一次看到3Blue1Brown的视频时,那种将抽象数学概念转化为流畅动画的能力让我震撼。作为一款基于Python的开源数学动画引擎,Manim最大的魅力在于它能让数学可视化变得像写代码一样简单。我见过很多数学老师用PPT制作动画,往往需要花费数小时调整关键帧,而在Manim里只需要几行代码就能实现更专业的效果。
对于编程新手来说,Manim的学习曲线其实很友好。它不需要你掌握复杂的图形学知识,只要会基础的Python语法就能上手。我在教学实践中发现,即使是完全没有编程经验的学生,通过20小时的系统学习也能独立制作出漂亮的数学动画。这比学习After Effects或Blender这类专业软件要高效得多。
很多初学者在第一步安装Python时就容易踩坑。我强烈建议使用Miniconda来管理Python环境,这样可以避免系统Python环境被污染。具体操作步骤如下:
bash复制conda create -n manim python=3.9
conda activate manim
注意要选择Python 3.7-3.9版本,目前Manim对Python 3.10+的支持还不够完善。我遇到过学生使用最新版Python导致依赖冲突的情况,回退到3.9就解决了。
视频渲染依赖FFmpeg,这里有个隐藏的坑:一定要将FFmpeg添加到系统环境变量。Windows用户可以在PowerShell中运行:
powershell复制ffmpeg -version
如果提示命令不存在,需要手动将ffmpeg.exe所在目录添加到Path环境变量。我在线下教学时,这个问题能卡住近30%的初学者。
官方推荐的安装命令是:
bash复制pip install manimgl
但国内用户更建议使用清华镜像源:
bash复制pip install manimgl -i https://pypi.tuna.tsinghua.edu.cn/simple
安装完成后,可以运行一个简单测试:
python复制from manim import *
class TestScene(Scene):
def construct(self):
circle = Circle()
self.play(Create(circle))
保存为test.py后执行:
bash复制manimgl test.py TestScene
如果看到弹出的视频窗口中有动画圆出现,说明环境配置成功。
每个Manim动画都继承自Scene类,construct方法是必须实现的入口函数。我刚开始学习时,常常忘记在方法里写self参数,导致奇怪的报错。一个标准的场景结构应该是:
python复制class MyFirstAnimation(Scene):
def construct(self):
# 你的动画代码
pass
创建基本图形非常简单:
python复制square = Square(side_length=2, color=BLUE)
circle = Circle(radius=1, fill_opacity=0.5)
但这里有个新手容易忽略的点:所有图形默认都出现在画面中心。如果想调整位置,可以使用:
python复制square.shift(LEFT*2)
circle.shift(RIGHT*2)
Manim提供了丰富的动画效果,最常用的是Create、FadeIn、Transform等。我在早期经常犯的错误是忘记调用self.play():
python复制self.play(Create(square)) # 正确
Create(square) # 错误,不会产生动画
更复杂的动画可以这样组合:
python复制self.play(
Rotate(square, angle=PI/2),
FadeIn(circle),
run_time=2 # 动画持续时间
)
在创建箭头或标注时,buff参数经常让人困惑。经过多次测试我发现:
python复制arrow = Arrow(start=LEFT, end=RIGHT, buff=0.1)
这里的buff控制的是箭头两端与起点/终点的距离。设置为0时箭头会紧贴端点,适当增大可以让布局更美观。
origin参数决定变换的基准点。比如旋转一个正方形:
python复制square.rotate(PI/4, about_point=ORIGIN) # 绕中心旋转
square.rotate(PI/4, about_point=RIGHT) # 绕右边中点旋转
我建议新手在调试时添加一个Dot标记origin位置:
python复制self.add(Dot(point=ORIGIN, color=RED))
Manim使用三维坐标系,但默认显示的是xy平面。z轴的正方向指向屏幕外。这个特性在做3D动画时很重要:
python复制cube = Cube()
self.play(Rotate(cube, axis=UP, radians=PI/4))
除了预设颜色,还可以使用HEX值:
python复制my_color = "#FF5733"
text = Text("Hello", color=my_color)
rate_func参数可以改变动画速度曲线:
python复制self.play(
MoveAlongPath(dot, circle),
rate_func=linear, # 匀速
# rate_func=smooth, # 平滑加减速
run_time=3
)
添加临时显示对象可以帮助定位问题:
python复制self.add(
Axes(), # 显示坐标轴
DotGrid(), # 显示网格点
debug=True # 开启调试模式
)
让我们用所学知识制作一个正弦函数动画:
python复制class SinFunction(Scene):
def construct(self):
axes = Axes(
x_range=[-3, 3],
y_range=[-1.5, 1.5],
axis_config={"color": BLUE}
)
graph = axes.plot(
lambda x: np.sin(x),
color=GREEN
)
dot = Dot(color=RED).move_to(
axes.c2p(0, np.sin(0))
)
self.play(Create(axes), run_time=1.5)
self.play(Create(graph), run_time=2)
self.play(FadeIn(dot))
def update_dot(mob):
mob.move_to(axes.c2p(
self.time, np.sin(self.time)
))
dot.add_updater(update_dot)
self.wait(2*PI)
dot.remove_updater(update_dot)
这个例子展示了如何:
官方文档是最权威的学习资料,但新手可能会觉得内容太多。我建议按这个顺序学习:
中文社区也有不少优质资源:
我在教学过程中整理了一份常见错误清单,包括: