Manim

本篇博客记录使用Manim引擎渲染好看的动画的学习过程。

在学线性代数的过程对Grant Sanderson大佬自制的manim数学引擎制作的动画秀到了,我也学了一下,python的图像处理真是太奇妙了!

Reference materials include:


3B1B 动画的制作思路是:根据自己想在场景中展现的内容和效果编写一系列的类,然后通过命令行对每个类进行实例化,前面输入的测试命令其实就包含了类的实例化过程,而每个类被实例化后都将得到一个动画片段,通过视频制作软件将各个片段衔接起来并配音,就能得到大家喜闻乐见的 3B1B 教学动画了。

1. 弹出的窗口中会播放一个绘制正方形并变换为圆的动画

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
from manimlib import *
class SquareToCircle(Scene):
def construct(self):
circle = Circle()
circle.set_fill(BLUE, opacity=0.5)
circle.set_stroke(BLUE_E, width=4)
square = Square()

self.play(ShowCreation(square))
self.wait()
self.play(ReplacementTransform(square, circle))
self.wait()

# 在代码的末尾加上如下一行来启用交互
# self.embed()
## # 在水平方向上拉伸到四倍
## play(circle.animate.stretch(4, dim=0))
# # 旋转90°
# play(Rotate(circle, TAU / 4))
# # 在向右移动2单位同时缩小为原来的1/4
# play(circle.animate.shift(2 * RIGHT), circle.animate.scale(0.25))
# # 为了非线性变换,给circle增加10段曲线(不会播放动画)
# circle.insert_n_curves(10)
# # 给circle上的所有点施加f(z)=z^2的复变换
# play(circle.animate.apply_complex_function(lambda z: z**2))
# # 关闭窗口并退出程序
# exit()

# 运行指令
manimgl start.py SquareToCircle
# 运行并保存
manimgl start.py SquareToCircle -ow

2 命令行参数和配置

manimgl <code>.py <Scene> <flags>
- .py : 你写的 python 文件
- : 你想要渲染的场景'
- : 传入的选项
- -w 把场景写入文件
- -o 把场景写入文件并打开
- -s 跳到最后只展示最后一帧
- -so 保存最后一帧并打开
- -n 跳到场景中第 n 个动画
- -f 打开窗口全屏

local configuration file D:\Manim\manim-master\custom_config.yml. You can manually modify it.也可以对于不同目录使用不同的 custom_config.yml,子文件夹下的配置文件会在运行时覆盖根目录下的总局配置文件。

1
2
3
4
5
6
7
8
9
10
manim/
├── manimlib/
│ ├── animation/
│ ├── ...
│ ├── default_config.yml
│ └── window.py
├── project/
│ ├── code.py
│ └── custom_config.yml
└── custom_config.yml

3 样例学习

3.1 Animating Methods

这个动画会出现一个Π的方阵,然后方阵集体向左移动,再变为渐变色,再旋转变为一个万花筒视角

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
class AnimatingMethods(Scene):
def construct(self):
# .get_grid() 方法会返回一个由该物体复制得到的阵列
grid = Tex(r"\pi").get_grid(10, 10, height=4)
self.add(grid)

# 你可以通过.animate语法来动画化物件变换方法
self.play(grid.animate.shift(LEFT))

# 或者你可以使用旧的语法,把方法和参数同时传给Scene.play
self.play(grid.shift, LEFT)

# 这两种方法都会在mobject的初始状态和应用该方法后的状态间进行插值
# 在本例中,调用grid.shift(LEFT)会将grid向左移动一个单位

# 这种用法可以用在任何方法上,包括设置颜色
self.play(grid.animate.set_color(YELLOW))
self.wait()
self.play(grid.animate.set_submobject_colors_by_gradient(BLUE, GREEN))
self.wait()
self.play(grid.animate.set_height(TAU - MED_SMALL_BUFF))
self.wait()

# 方法Mobject.apply_complex_function允许应用任意的复函数
# 将把Mobject的所有点的坐标看作复数

self.play(grid.animate.apply_complex_function(np.exp), run_time=5)
self.wait()

# 更一般地说,你可以应用Mobject.apply方法,它接受从R^3到R^3的一个函数
self.play(
grid.animate.apply_function(
lambda p: [
p[0] + 0.5 * math.sin(p[1]),
p[1] + 0.5 * math.sin(p[0]),
p[2]
]
),
run_time=5,
)
self.wait()

3.2 TextExample

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
class TextExample(Scene):
def construct(self):
# 想要正确运行这个场景,你需要确保你的计算机中安装了Consolas字体
# 关于Text全部用法,请见https://github.com/3b1b/manim/pull/680
# Text 可以创建文字,定义字体等
text = Text("Here is a text", font="Consolas", font_size=90)
difference = Text(
"""
The most important difference between Text and TexText is that\n
you can change the font more easily, but can't use the LaTeX grammar
""",
font="Arial", font_size=24,
# t2c是一个由 文本-颜色 键值对组成的字典
t2c={"Text": BLUE, "TexText": BLUE, "LaTeX": ORANGE}
)
# VGroup 可以将多个 VMobject 放在一起看做一个整体。
# 例子中调用了 arrange() 方法来将其中子物体依次向下排列(DOWN),且间距为 buff
VGroup(text, difference).arrange(DOWN, buff=1)
# Write 是显示类似书写效果的动画
self.play(Write(text))
# FadeIn 将物体淡入,第二个参数表示淡入的方向
self.play(FadeIn(difference, UP))
self.wait(3)

fonts = Text(
"And you can also set the font according to different words",
font="Arial",
t2f={"font": "Consolas", "words": "Consolas"},
t2c={"font": BLUE, "words": GREEN}
)
fonts.set_width(FRAME_WIDTH - 1)
slant = Text(
"And the same as slant and weight",
font="Consolas",
t2s={"slant": ITALIC},
t2w={"weight": BOLD},
t2c={"slant": ORANGE, "weight": RED}
)
VGroup(fonts, slant).arrange(DOWN, buff=0.8)
# FadeOut 将物体淡出,第二个参数表示淡出的方向
self.play(FadeOut(text), FadeOut(difference, shift=DOWN))
self.play(Write(fonts))
self.wait()
self.play(Write(slant))
self.wait()

3.3 TexTransformExample

https://docs.manim.org.cn/getting_started/example_scenes.html


Manim
http://example.com/2024/06/01/5_Manim/
Author
Xi Wang
Posted on
June 1, 2024
Licensed under