边学边做Manim的基础知识

概述

Manim(Manim Community Edition)是由3Blue1Brown的Grant Sanderson开发的数学动画引擎,专为数学和科学可视化设计。它结合了Python的灵活性与LaTeX的精确性,支持多领域的内容展示,能生成清晰、精确的数学动画,广泛应用于教育视频制作。安装简单,入门容易,适合教育工作者和编程爱好者使用。

开始一个新项目

首先创建一个新文件夹,命名为:project,此文件夹是项目的根文件夹,它包含 Manim 运行所需的所有文件,以及项目产生的所有输出。

设置圆的动画

1、打开文本编辑器,复制以下代码:

1
2
3
4
5
6
7
8
from manim import *

class CreateCircle(Scene):
def construct(self):
circle = Circle() # create a circle
circle.set_fill(PINK, opacity=0.5) # set the color and transparency
self.play(Create(circle)) # show the circle on screen

2、将代码片段保存到项目文件夹中,名称为:scene.py

1
2
3
project/
└─scene.py

3、打开命令行,定位到项目文件夹,执行以下命令:

1
2
manim -pql scene.py CreateCircle

Manim 将输出渲染信息,并创建一个 MP4 文件。您的默认播放器将播放 MP4 文件,并显示以下动画。

在这里插入图片描述

代码解释

第一行导入库的所有内容:

1
from manim import *

接下来的两行为编写动画脚本的类 Scene 和方法 construct( ),在 construct( ) 中可以创建对象,在屏幕显示它们,并为它们设置动画。

1
2
3
class CreateCircle(Scene):
def construct(self):
...

接下来的两行创建一个圆并设置其颜色和不透明度:

1
2
circle = Circle()  # create a circle
circle.set_fill(PINK, opacity=0.5) # set the color and transparency

最后一行使用动画 Create 在屏幕上显示圆:

1
self.play(Create(circle))  # show the circle on screen

将正方形转换为圆形

1、打开scene.py ,并在类 CreateCircle下方添加以下代码片段:

1
2
3
4
5
6
7
8
9
10
11
class SquareToCircle(Scene):
def construct(self):
circle = Circle() # create a circle
circle.set_fill(PINK, opacity=0.5) # set color and transparency

square = Square() # create a square
square.rotate(PI / 4) # rotate a certain amount

self.play(Create(square)) # animate the creation of the square
self.play(Transform(square, circle)) # interpolate the square into the circle
self.play(FadeOut(square)) # fade out animation

2、在命令行中运行以下命令渲染 SquareToCircle:

1
manim -pql scene.py SquareToCircle

将呈现以下动画:

在这里插入图片描述

定位

1、打开 scene.py,并在类 SquareToCircle 下方添加以下代码片段:

1
2
3
4
5
6
7
8
9
10
class SquareAndCircle(Scene):
def construct(self):
circle = Circle() # create a circle
circle.set_fill(PINK, opacity=0.5) # set the color and transparency

square = Square() # create a square
square.set_fill(BLUE, opacity=0.5) # set the color and transparency

square.next_to(circle, RIGHT, buff=0.5) # set the position
self.play(Create(circle), Create(square)) # show the shapes on screen

2、在命令行中运行以下命令渲染 SquareAndCircle:

1
manim -pql scene.py SquareAndCircle

将呈现以下动画:

在这里插入图片描述

next_to 是一种定位的方法,该方法第一个参数指定粉红色圆为正方形的参考点,第二个参数指定相对于参考点的放置方向。在本例中,我们将方向设置为 RIGHT,即将正方形定位在圆的右侧。 最后,在两个对象之间应用一个小距离缓冲区 buff=0.5。

使用语法 .animate 对进行动画处理

.animate 是一种 Mobject 方法,用于为对 Mobject 所做的更改设置动画。当你在任何更改 Mobject 的方法调用前加上 .animate 时,该方法就会变成一个可以使用 self.play 播放的动画。让我们回到 SquareToCircle,看看在创建 Mobject 时使用方法与使用 .animate 为这些方法调用设置动画之间的区别。

1、打开 scene.py,并在类 SquareAndCircle下方添加以下代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
class AnimatedSquareToCircle(Scene):
def construct(self):
circle = Circle() # create a circle
square = Square() # create a square

self.play(Create(square)) # show the square on screen
self.play(square.animate.rotate(PI / 4)) # rotate the square
self.play(
ReplacementTransform(square, circle)
) # transform the square into a circle
self.play(
circle.animate.set_fill(PINK, opacity=0.5)
) # color the circle on screen

2、在命令行中运行以下命令渲染 AnimatedSquareToCircle:

1
manim -pql scene.py AnimatedSquareToCircle

将呈现以下动画:

在这里插入图片描述

第一个self.play创建了正方形,第二个self.play将其旋转45度,第三个self.play将正方形转换为圆形,最后一个self.play将圆形填充粉红色。虽然最终结果与 SquareToCircle相同,但 .animate显示了动态应用于Mojectrotateset_fill,而不是使用已应用的更改来创建它们。

3、打开scene.py,并在类AnimatedSquareToCircle下面添加以下代码片段:

1
2
3
4
5
6
7
8
class DifferentRotations(Scene):
def construct(self):
left_square = Square(color=BLUE, fill_opacity=0.7).shift(2 * LEFT)
right_square = Square(color=GREEN, fill_opacity=0.7).shift(2 * RIGHT)
self.play(
left_square.animate.rotate(PI), Rotate(right_square, angle=PI), run_time=2
)
self.wait()

4、在命令行中运行以下命令渲染DifferentRotations:

1
manim -pql scene.py DifferentRotations

将呈现以下动画:

这个场景展示了**.animate的不同,当使用 .animate时Manim实际上会获取Moject**的开始与结束状态,并对两者进行插值。

在类AnimatedSquareToCircle中,当正方形旋转时,您可以观察到这一点:

当正方形的角移动到第一个正方形变换为第二个正方形所需的位置时,它们看起来会稍微收缩。

DifferentRotations中,.animate 对旋转的解释与方法 Rotate 之间的差异要明显得多。旋转360度的Moject的开始和结束状态是相同的,因此 .animate 尝试对两个相同的对象进行插值,结果是左正方形。如果您发现自己对 .animate 的使用导致了类似的不需要的行为,请考虑使用传统的动画方法,例如使用 Rotate 。