快速入门

注意

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

重要提示

如果您以推荐的方式安装了Manim,即使用Python管理工具uv,那么您需要确保相应的虚拟环境已激活(按照运行uv venv时打印的说明操作),或者您需要记住在控制台中执行manim命令时加上uv run前缀;即,uv run manim ...

概览

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

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

开始一个新项目

首先创建一个新文件夹

manim init project my-project --default

my-project文件夹是您项目的根文件夹。它包含Manim所需的所有文件以及项目生成的所有输出。

动画一个圆形

  1. 打开一个文本编辑器,如记事本。打开my-project文件夹中的main.py文件。它应该看起来像这样

    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. 打开命令行,导航到您的项目文件夹,并执行以下命令

    manim -pql main.py CreateCircle
    

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

如果您看到一个粉色圆形被绘制的动画,恭喜!您刚刚从头编写了您的第一个Manim场景。

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

解释

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

第一行导入库的所有内容

from manim import *

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

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

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

大多数情况下,用于编写动画脚本的代码完全包含在Scene类的construct()方法中。在construct()内部,您可以创建对象、在屏幕上显示它们并动画化它们。

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

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

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

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

提示

所有动画都必须位于从Scene派生的类中的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的主要功能之一:只需几行代码即可实现复杂且数学密集型动画(例如在两种几何形状之间平滑插值)。

定位Mobject

接下来,让我们回顾一些定位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_toMobject用于定位Mobject的方法。

我们首先通过将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 vs ReplacementTransform

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

另一方面,ReplacementTransform(mob1, mob2)则直接在场景中用mob2替换mob1

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

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更有益,例如当您连续变换多个mobject时。以下代码避免了需要保留对上次变换的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功能的概览以及其配置和其他设置的信息,请查阅其他教程。有关所有可用功能的列表,请参阅参考手册页面。