在Manim中如何表示对象移动

Manim中,很多的动画都会用到物体对象的移动,今天我们来汇总一下在Manim中如何移动对象。

1.shift()

shift以自身为参考,直接对物体操作,沿指定方向向量移动,方向可使用预定义常量(如UP、DOWN、LEFT、RIGHT)或自定义向量(如UP + LEFT表示对角线移动),所以说shift执行的是相对位移,如果你创建一个对象在某个位置,然后调用 shift(UP),它会从当前位置向上移动 1 个单位。

shift方法它不改变对象的内部属性(如半径、顶点等),只修改对象的 points 数组,为每个点加上位移向量,基于当前坐标位置进行位移。

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

class CompareMovesShift(Scene):
def construct(self):
# 创建四个正方形
s1 = Square().set_color(RED)
s2 = Square().set_color(GREEN)
s3 = Square().set_color(BLUE)
s4 = Square().set_color(YELLOW)

# 先显示所有正方形在原点(重叠)
self.play(Create(s1), Create(s2), Create(s3), Create(s4))
self.wait(0.5)

# 逐一移动到不同位置
self.play(s1.animate.shift(UP * 2)) # 向上移动2
self.wait(0.3)
self.play(s2.animate.shift(LEFT * 2)) # 向左移动2
self.wait(0.3)
self.play(s3.animate.shift(DOWN * 2)) # 向下移动2
self.wait(0.3)
self.play(s4.animate.shift(RIGHT * 2)) # 向右移动2
self.wait(2)

常用的表达式为

1
obj.shift(预定义常量) 

效果演示如下

2.move_to()

obj.move_to()是将元素移动到场景中的绝对坐标位置(格式为[x, y, z]),所以说 obj.move_to()是绝对定位方法,它将对象的中心点移动到指定的目标位置。

1
2
3
4
5
obj.move_to(
point_or_mobject, # 目标位置或参考对象
aligned_edge=ORIGIN, # 对齐边缘
coor_mask=np.array([1, 1, 1]) # 坐标轴掩码
)

我们来看演示代码

1
2
3
4
5
6
7
8
9
10
11
12
from manim import *

class MoveToExample(Scene):
def construct(self):
# 先创建在默认位置(屏幕中心)
circle = Circle(color=RED, radius=0.5)
# 显示创建动画
self.play(Create(circle))
self.wait(0.5)
# 然后动画移动到新位置
self.play(circle.animate.move_to(np.array([3, 2, 0])))
self.wait()

来看演示的效果

1
.move_to(np.array([3, 2, 0]))

我们用一个数组表示了一个点的坐标,也就是把圆平移到了[3, 2, 0]的位置。

3.next_to()

next_to() 用于将对象放置到另一个对象的旁边,保持一定的间距。它特别适合相对布局。

1
2
3
4
5
6
obj.next_to(
mobject_or_point, # 参考对象或点
direction=RIGHT, # 放置方向
buff=DEFAULT_MOBJECT_TO_MOBJECT_BUFFER, # 间距
aligned_edge=ORIGIN # 对齐方式
)

我们来看实例代码

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

class NextToExample(Scene):
def construct(self):
square = Square(color=BLUE)

# 不同间距的圆
circle1 = Circle(color=RED, radius=0.3)
circle2 = Circle(color=GREEN, radius=0.3)
circle3 = Circle(color=YELLOW, radius=0.3)

# 动画:逐个飞到位置
self.play(Create(square))
self.wait(0.2)

self.play(circle1.animate.next_to(square, RIGHT, buff=0.1))
self.wait(0.2)

self.play(circle2.animate.next_to(square, RIGHT, buff=1.0))
self.wait(0.2)

self.play(circle3.animate.next_to(square, RIGHT, buff=2.0))
self.wait(1)

来看演示的效果

为了显示动画效果,我们使用的动画参数,只是为了方便大家了解这个相对参数。

4.做个总结

next_to() - 旁边放

1
circle.next_to(square, RIGHT, buff=2.0)  # 圆放在正方形右边

move_to() - 移动到点

1
circle.move_to([1, 2, 0])  # 移动到坐标(1,2)

或者使用数组

1
circle.move_to(np.array([3, 2, 0]))  # 移动到坐标(3,2)

shift() - 看自身

1
circle.shift(UP * 2)  # 相较于自己的位置在向上移动2单位

在这里多说一句,还有一个align_to ,不过align_toManim中用于对齐两个对象的重要方法,属于 Mobject(所有可显示对象的基类)的方法之一。有时间我们再探究这个问题。同时,如果不添加动画效果的话,生成的图形会直接显示在目标区,这也是为什么给这三个参数叫做瞬移的原因。