3Blue1Brown 动画制作教程(9)--变化多端的相机
变化多端的相机
前面的文章中,场景在建立了之后,我们的视角及视野范围往往是不变的,如果需要显示一个局部细节,只能去放大场景中各种对象的尺寸,这样操作起来就显得很不灵活,所以在 manim 中包含了“camera(相机)”的概念。本文的代码参考 Alexander Vázquez 的 Github 中的项目,并对项目中代码进行了分类、简化与释义,形成本文。
相机的定位、缩放及恢复
新建一个 Python 文件,例如名字为 Camera_ex.py。在文件的开头部分写上:
from manimlib.imports import *
将所有生成动画所需的模块导入。
再添加以下代码:
class ChangePositionAndSizeCamera(MovingCameraScene):
def construct(self):
text=TexMobject("\\nabla\\textbf{u}").scale(3)
square=Square()
# Arrange the objects
VGroup(text,square).arrange_submobjects(RIGHT,buff=3)
self.add(text,square)
# Save the state of camera
self.camera.frame.save_state()
# Animation of the camera
self.play(
# Set the size with the width of a object
self.camera.frame.set_width,text.get_width()*1.2,
# Move the camera to the object
self.camera.frame.move_to,text
)
self.wait()
# Restore the state saved
self.play(Restore(self.camera.frame))
self.play(
self.camera.frame.set_height,square.get_width()*1.2,
self.camera.frame.move_to,square
)
self.wait()
self.play(Restore(self.camera.frame))
self.wait()
该场景继承于 MovingCameraScene 类,而 MovingCameraScene 类又是继承于 Scene 基本场景类。
先新建了一个名为 text 的公式及一个名为 square 的正方形,然后通过 VGroup 将两个对象横向组成一个组合,间距为三个单位。
下面的动画展示部分,先将 text 和 square 添加到页面当中,然后通过 self.camera.frame.save_state() 储存当前的相机位置及视野(场景中的默认相机位置及视野)。
利用 self.play() 方法,先设置相机的宽度为 text 的宽度的1.2倍: self.camera.frame.set_width,text.get_width()*1.2 ,并将相机的中心移动到 text 的中心:self.camera.frame.move_to,text。
等待1秒。
利用 Restore(self.camera.frame) 方法使用刚刚储存的相机位置及视野,恢复到初始的相机的位置及视野。
利用 self.play() 方法,先设置相机的高度为 square 的宽度的1.2倍: self.camera.frame.set_height,square.get_width()*1.2 ,并将相机的中心移动到 square 的中心:self.camera.frame.move_to,square。
等待1秒。
利用 Restore(self.camera.frame) 方法使用刚刚储存的相机位置及视野,恢复到初始的相机的位置及视野。
等待1秒。
动画如下:
相机的缩放与移动
再在下面添加以下代码:
class ChangePositionAndSizeCameraInAnotherScene(GraphScene,MovingCameraScene):
CONFIG = {
"y_max" : 50,
"y_min" : 0,
"x_max" : 7,
"x_min" : 0,
"y_tick_frequency" : 5,
"x_tick_frequency" : 0.5,
}
def construct(self):
self.setup_axes(animate=False)
graph = self.get_graph(lambda x : x**2,
color = GREEN,
x_min = 0,
x_max = 7
)
dot_at_start_graph=Dot().move_to(graph.points[0])
dot_at_end_grap=Dot().move_to(graph.points[-1])
self.add(graph,dot_at_end_grap,dot_at_start_graph)
self.play(
self.camera.frame.scale,0.5,
self.camera.frame.move_to,dot_at_start_graph
)
self.wait()
self.play(
self.camera.frame.move_to,dot_at_end_grap, run_time = 2
)
self.wait()
该场景继承于两个父类,一个是用于构建二维坐标系的场景类 GraphScene,另一个是前面那个例子也用到的 MovingCameraScene 类。
首先用 CONFIG{} 字典,设置了二维坐标系的一些参数。
通过 self.setup_axes(animate=False) 方法设置坐标系显示时为非动画显示。
然后定义了一个 y=x^2 的函数曲线。
通过索引找到函数曲线上的起始点和终止点,并在这两个点处分别创建一个图形点。
注意 Python 中的 list 索引号的定义是:list 中的第一个元素的索引号为[0],第二个元素的索引号为 [1],最后一个元素的索引号为[-1],倒数第二个元素的索引号为[-2]。
动画部分先将二维函数图及坐标系以及两个点展现出来,然后将相机视野改为默认视野的一半,并将相机中心置于函数起始点处,并以动画形式展现这部分的变化过程。
等待1秒。
再将相机中心移动到函数终止点处,相机视野大小不变,并以动画形式展现这部分的变化过程。
等待1秒。
动画如下:
小结
利用相机可以灵活地操作场景的视野范围及位置,对于后面将要介绍的三维坐标系场景而言,还可以通过定义相机的参数改变观察视角,使得画面看起来变化莫测,局部显示效果更加流畅。
3B1B 动画制作教程持续更新中...
更多内容请关注知乎专栏: