以下教程来自:Manim Community v0.16.0.post0

Manim中最基本的三元素:Mobject, Animation, 和Scene

Mobjects

一般来说可以显示在屏幕上的,可以有动画的都是Mobject,比如CircleArrowAxesFunctionGraphBarChart

Mobject类本身用于其他实例对象的继承,自身并不能显示。他的一个实例是VMobject,代表用vector graphics来显示图像。大多数情况下我们使用的都是VMobject

Creating and displaying mobjects

如果要将没有动画的实例显示出来,使用add()方法;而使用remove()可以从屏幕中删除mobject

使用shift()可以移动对象,其他移动对象的方式还有move_to()next_to()align_to()

move_to:绝对位置

next_to:相对位置

align_to:用于对齐边界

Styling mobjects

set_stroke改变边界样式

set_fill改变内部样式

只有VMobject的实例实现了这两个方法

Mobject on-screen order

self.add(circle, triangle, square)加入的顺序靠前,则图形置于底层

Animations

1
2
3
self.play(FadeIn(square))
self.play(Rotate(square, PI/))
self.play(FadeOut(square))

animate()是所有mobject的一个属性,他可以将设置变为动画

1
self.play(square.animate.setfill(WHITE).shift(UP).rotate(PI/3))

Animation run time

默认情况下,所有动画播放正好一秒,可以在play方法里修改

1
self.play(circle.animate.shift(UP), run_time=4)

Creating a custom animation

You can define your own custom animation!

只需要==继承Animation类==,然后==重写interpolate_mobject()方法==,这个方法有一个参数$$\alpha$$,表示动画完成的比率(0-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
from manim import *

class Count(Animation):
def __init__(self, number: DecimalNumber, start: float, end: float, **kwargs) -> None:
# Pass number as the mobject of the animation
super().__init__(number, **kwargs)
# Set start and end
self.start = start
self.end = end

def interpolate_mobject(self, alpha: float) -> None:
# Set value of DecimalNumber according to alpha
value = self.start + (alpha * (self.end - self.start))
self.mobject.set_value(value)


class CountingScene(Scene):
def construct(self):
# Create Decimal Number and add it to scene
number = DecimalNumber().set_color(WHITE).scale(5)
# Add an updater to keep the DecimalNumber centered as its value changes
number.add_updater(lambda number: number.move_to(ORIGIN))

self.add(number)

self.wait()

# Play the Count Animation to count from 0 to 100 in 4 seconds
self.play(Count(number, 0, 100), run_time=4, rate_func=linear)

self.wait()

Using coordinates of a mobject

manim的坐标系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from manim import *

class MobjectExample(Scene):
def construct(self):
p1= [-1,-1,0]
p2= [1,-1,0]
p3= [1,1,0]
p4= [-1,1,0]
a = Line(p1,p2).append_points(Line(p2,p3).points).append_points(Line(p3,p4).points)
point_start= a.get_start()
point_end = a.get_end()
point_center = a.get_center()
self.add(Text(f"a.get_start() = {np.round(point_start,2).tolist()}", font_size=24).to_edge(UR).set_color(YELLOW))
self.add(Text(f"a.get_end() = {np.round(point_end,2).tolist()}", font_size=24).next_to(self.mobjects[-1],DOWN).set_color(RED))
self.add(Text(f"a.get_center() = {np.round(point_center,2).tolist()}", font_size=24).next_to(self.mobjects[-1],DOWN).set_color(BLUE))

self.add(Dot(a.get_start()).set_color(YELLOW).scale(2))
self.add(Dot(a.get_end()).set_color(RED).scale(2))
self.add(Dot(a.get_top()).set_color(GREEN_A).scale(2))
self.add(Dot(a.get_bottom()).set_color(GREEN_D).scale(2))
self.add(Dot(a.get_center()).set_color(BLUE).scale(2))
self.add(Dot(a.point_from_proportion(0.5)).set_color(ORANGE).scale(2))
self.add(*[Dot(x) for x in a.points])
self.add(a)

Transforming mobjects into other mobjects

1
self.play(Transform(obj1, obj2))

这个函数是通过点对点的映射实现的,可能导致一些奇怪的行为比如当两个图形的点排列方向不同的时候,可以用flip翻转图像,以及nummpy中的roll对图像进行滚动

Scenes

一个场景包含就是一个继承了Scene的类,里面有多个Mobjects,可以同时渲染多个场景