快速入门

注意

在继续之前,请按照安装中的步骤安装Manim并确保其正常运行。有关在Jupyterlab或Jupyter笔记本中使用Manim的信息,请参阅IPython magic command的文档,%%manim

概述

本快速入门指南将引导您使用Manim创建一个示例项目:一个用于精确程序化动画的动画引擎。

首先,您将使用命令行界面创建一个Scene,这是Manim生成视频的类。在Scene中,您将为一个圆形添加动画。然后,您将添加另一个Scene,展示一个正方形如何转变为圆形。这将是对Manim动画能力的初步介绍。之后,您将定位多个数学对象(Mobjects)。最后,您将学习.animate语法,这是一个强大的功能,可以动画化您用来修改Mobjects的方法。

开始一个新项目

首先创建一个新文件夹。在本指南中,将文件夹命名为 project

project/

此文件夹是您项目的根文件夹。它包含Manim运行所需的所有文件,以及您的项目生成的任何输出。

动画化一个圆圈

  1. 打开一个文本编辑器,例如记事本。将以下代码片段复制到窗口中:

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
  1. 将代码片段保存到您的项目文件夹中,命名为scene.py

project/
└─scene.py

3. 打开命令行,导航到您的项目文件夹,并执行以下命令:

manim -pql scene.py CreateCircle

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

如果你看到一个粉红色圆圈被绘制的动画,恭喜你! 你刚刚从零开始编写了你的第一个Manim场景。

如果您收到错误消息,看不到视频,或者视频输出不像前面的动画那样,很可能Manim没有正确安装。请参考我们的FAQ部分以获取有关最常见问题的帮助。

解释

让我们逐行查看你刚刚执行的脚本,看看Manim是如何绘制圆的。

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

from manim import *

这是推荐的使用Manim的方式,因为单个脚本通常使用Manim命名空间中的多个名称。在你的脚本中,你导入并使用了SceneCirclePINKCreate

现在让我们看看接下来的两行:

class CreateCircle(Scene):
    def construct(self):
        [...]

大多数情况下,编写动画的代码完全包含在construct()方法中,该方法属于场景类。在construct()内部,您可以创建对象,将它们显示在屏幕上,并对它们进行动画处理。

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

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

提示

所有动画必须位于从场景派生的类的construct()方法内。其他代码,如辅助或数学函数,可以位于类之外。

将正方形转换为圆形

我们的圆形动画完成后,让我们继续做一些稍微复杂的事情。

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

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
  1. 通过运行以下命令在命令行中渲染 SquareToCircle

manim -pql scene.py SquareToCircle

以下动画将呈现:

这个例子展示了Manim的主要特性之一:能够用几行代码实现复杂且数学密集的动画(例如在两个几何形状之间进行干净的插值)。

定位 Mobjects

接下来,我们将介绍一些用于定位Mobject的基本技巧。

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

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
  1. 通过在命令行中运行以下命令来渲染 SquareAndCircle

manim -pql scene.py SquareAndCircle

以下动画将呈现:

next_to 是一个用于定位 MobjectMobject 方法。

我们首先通过将circle作为方法的第一个参数来指定粉色圆圈为正方形的参考点。 第二个参数用于指定Mobject相对于参考点的放置方向。 在这种情况下,我们将方向设置为RIGHT,告诉Manim将正方形放置在圆圈的右侧。 最后,buff=0.5在两个对象之间应用了一个小的距离缓冲。

尝试将RIGHT改为LEFTUPDOWN,看看这如何改变方块的位置。

使用定位方法,您可以在场景中渲染多个Mobject,使用坐标设置它们在场景中的位置,或者将它们相对于彼此进行定位。

有关next_to和其他定位方法的更多信息,请查看我们参考手册中的Mobject方法列表。

使用.animate语法来动画化方法

本教程的最后一课是使用.animate,这是一个Mobject方法,它可以动画化你对Mobject所做的更改。当你在任何修改Mobject的方法调用前加上.animate时,该方法就会变成一个可以使用self.play播放的动画。让我们回到SquareToCircle,看看在创建Mobject时使用方法和使用.animate动画化这些方法调用之间的区别。

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

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(Transform(square, circle))  # transform the square into a circle
        self.play(
            square.animate.set_fill(PINK, opacity=0.5)
        )  # color the circle on screen
  1. 通过在命令行中运行以下命令来渲染 AnimatedSquareToCircle

manim -pql scene.py AnimatedSquareToCircle

以下动画将呈现:

第一个self.play创建了正方形。第二个动画将其旋转45度。 第三个将正方形转换为圆形,最后一个将圆形着色为粉色。 尽管最终结果与SquareToCircle相同,.animate展示了 rotateset_fill被动态地应用于Mobject,而不是在创建时就已经应用了这些变化。

尝试其他方法,如flipshift,看看会发生什么。

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

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()
  1. 通过运行以下命令在命令行中渲染 DifferentRotations

manim -pql scene.py DifferentRotations

以下动画将呈现:

这个Scene展示了.animate的一些特性。当使用.animate时,Manim实际上会获取Mobject的初始状态和结束状态,并在两者之间进行插值。在AnimatedSquareToCircle类中,你可以观察到这一点,当正方形旋转时:正方形的角在移动到第一个正方形转换为第二个正方形所需的位置时,似乎会稍微收缩。

DifferentRotations中,.animate对旋转的解释与Rotate方法之间的差异更加明显。一个旋转180度的Mobject的起始和结束状态是相同的,因此.animate尝试插值两个相同的对象,结果是左边的正方形。如果你发现使用.animate导致类似的不希望的行为,考虑使用传统的动画方法,如右边的正方形,它使用了Rotate

Transform 对比 ReplacementTransform

TransformReplacementTransform 的区别在于,Transform(mob1, mob2)mob1 的点(以及其他属性如颜色)转换为 mob2 的点/属性。

ReplacementTransform(mob1, mob2) 另一方面,它实际上是用 mob2 替换场景中的 mob1

使用ReplacementTransformTransform主要取决于个人偏好。它们可以用来实现相同的效果,如下所示。

class TwoTransforms(Scene):
    def transform(self):
        a = Circle()
        b = Square()
        c = Triangle()
        self.play(Transform(a, b))
        self.play(Transform(a, c))
        self.play(FadeOut(a))

    def replacement_transform(self):
        a = Circle()
        b = Square()
        c = Triangle()
        self.play(ReplacementTransform(a, b))
        self.play(ReplacementTransform(b, c))
        self.play(FadeOut(c))

    def construct(self):
        self.transform()
        self.wait(0.5)  # wait for 0.5 seconds
        self.replacement_transform()

然而,在某些情况下,使用Transform更为有益,比如当你需要依次转换多个mobjects时。 下面的代码避免了必须保留对最后一个被转换的mobject的引用。

示例:TransformCycle

from manim import *

class TransformCycle(Scene):
    def construct(self):
        a = Circle()
        t1 = Square()
        t2 = Triangle()
        self.add(a)
        self.wait()
        for t in [t1,t2]:
            self.play(Transform(a,t))
class TransformCycle(Scene):
    def construct(self):
        a = Circle()
        t1 = Square()
        t2 = Triangle()
        self.add(a)
        self.wait()
        for t in [t1,t2]:
            self.play(Transform(a,t))

您已完成!

在成功安装Manim并掌握这个示例项目后,您已准备好开始创建自己的动画。要了解更多关于Manim底层工作原理的信息,请继续学习下一个教程:Manim的输出设置。要了解Manim的功能概述,以及其配置和其他设置,请查看其他教程。要获取所有可用功能的列表,请参阅参考手册页面。