相機(Camera)在二維的場景下使用不多,一般在3D場景中提及的比較多。 相機相當於我們看動畫的視角,簡單來理解的話,相當於我們的眼睛(實際情況會複雜一些,相機還有其他一些輔助功能)。 預設的相機焦點在屏幕的中心位置,相機預設是以俯視的視角查看所有的元素。 之前的介紹的常用動畫效果和高級動畫效果, ...
相機(Camera)在二維的場景下使用不多,一般在3D場景中提及的比較多。
相機相當於我們看動畫的視角,簡單來理解的話,相當於我們的眼睛(實際情況會複雜一些,相機還有其他一些輔助功能)。
預設的相機焦點在屏幕的中心位置,相機預設是以俯視的視角查看所有的元素。
之前的介紹的常用動畫效果和高級動畫效果,都沒有對相機進行調整過,
所以,是通過移動和變換各個元素來實現動畫效果。
本篇介紹的相機,則是另一種製作動畫的方式,它不改變元素在屏幕或者說在坐標系中的位置,
通過改變相機的位置和角度來實現動畫效果。
舉個現實世界中的簡單例子,如果有個杯子,我們可以通過轉動杯子來從各個角度觀察杯子;
而如果是一棟樓的話,我們無法移動它,只能圍著樓走一圈來觀察它,這個過程就相當於移動相機。
下麵通過一些實例來看看移動相機帶來的不一樣的動畫效果。
1. 相機移動
相機移動常用的兩種方式:
- 移動焦點:改變相機的焦點,焦點在那個元素,那個元素就會在屏幕中心
- 改變視野:改變相機與元素的距離,離得越遠,物體越小。
1.1 移動焦點
manim
中移動焦點要繼承 MovingCameraScene
類,
然後通過 self.camera.frame.animate.move_to
函數來移動焦點。
下麵的示例構造了一個正方形,一個三角形,然後通過改變焦點來形成元素移動的動畫。
實際上元素並沒有移動,它們的坐標始終沒變,變化的是相機的焦點。
class CameraSample1(MovingCameraScene):
def _move_focus(self):
s = Square(color=RED, fill_opacity=0.5)
t = Triangle(color=GREEN, fill_opacity=0.5)
vg = VGroup(s, t)
vg.arrange(RIGHT, buff=MED_LARGE_BUFF)
self.add(vg)
self.play(self.camera.frame.animate.move_to(s))
self.play(self.camera.frame.animate.move_to(t))
self.play(self.camera.frame.animate.move_to(vg))
def construct(self):
self._move_focus()
self.wait()
運行效果:
1.2 改變視野
改變視野通過 self.camera.frame.animate.set
方法,通過這個方法設置視野的寬度,可以形成縮放元素的效果。
下麵的示例,通過改變視野的寬度,讓元素出現放大和縮小的現象,實際上元素並沒有變化。
變化的是相機到元素的距離。
class CameraSample1(MovingCameraScene):
def _scale(self):
s = Square(color=RED, fill_opacity=0.5)
self.add(s)
self.camera.frame.save_state()
self.play(self.camera.frame.animate.set(width=s.width * 2))
self.wait(0.3)
self.play(self.camera.frame.animate.set(width=s.width * 8))
self.wait(0.3)
self.play(Restore(self.camera.frame))
def construct(self):
self._scale()
self.wait()
運行效果:
2. 鷹眼效果
鷹眼的效果是通過兩個相機來實現的,兩個相機的焦點一樣,但是視野不一樣。
鷹眼效果一般用在提供全局視圖的場合,特別是當元素特別多的時候。
下麵示例中,設置了兩個相機,縮放的參數為3,zoom_factor=3
。
class CameraSample2(ZoomedScene):
def __init__(self, **kwargs):
ZoomedScene.__init__(
self,
zoom_factor=3,
zoomed_display_height=1,
zoomed_display_width=2,
image_frame_stroke_width=5,
zoomed_camera_config={
"default_frame_stroke_width": 3,
},
**kwargs
)
def construct(self):
s = Square(color=RED, fill_opacity=0.5, side_length=1.5)
t = Triangle(color=GREEN, fill_opacity=0.5).scale(0.5)
vg = VGroup(s, t)
vg.arrange(RIGHT, buff=SMALL_BUFF)
self.add(vg)
self.activate_zooming(animate=False)
self.play(s.animate.shift(LEFT), t.animate.shift(RIGHT))
self.play(s.animate.rotate(2 * PI / 3), t.animate.rotate(PI / 2))
self.play(s.animate.shift(RIGHT), t.animate.shift(LEFT))
self.wait()
運行效果:
3. 追蹤物體
追蹤物體就是將相機的焦點定位在移動的物體上,就像我們坐在火車上的感覺一樣,那時,我們覺得火車沒動,而是車外的風景不斷向後移動。
下麵的示例是一個點沿著正弦曲線運動,我們將相機焦點定位在這個點上,感覺就像是曲線在移動。
class CameraSample3(MovingCameraScene):
def construct(self):
self.camera.frame.save_state()
graph = FunctionGraph(
lambda x: np.sin(x),
x_range=[-3, 3],
color=RED,
)
d = dot(graph.get_start())
self.add(graph, d)
self.play(self.camera.frame.animate.scale(0.5).move_to(d))
def update_curve(mob):
mob.move_to(d.get_center())
self.camera.frame.add_updater(update_curve)
self.play(MoveAlongPath(d, graph), rate_func=linear, run_time=2)
self.camera.frame.remove_updater(update_curve)
self.play(Restore(self.camera.frame))
運行效果:
4. 3D 場景
相機其實主要就是應用在3D場景中的,所以 manim
的3D場景類 ThreeDScene
中提供了一個非常方便的移動相機的方法 move_camera
。
下麵的示例中,我們用 move_camera
方法來改變視角和調整視野。
示例中的球其實一直沒動,也就是球上各點的坐標沒有改變過。
class CameraSample4(ThreeDScene):
def construct(self):
axes = ThreeDAxes()
sphere = Surface(
lambda u, v: np.array(
[
1.5 * np.cos(u) * np.cos(v),
1.5 * np.cos(u) * np.sin(v),
1.5 * np.sin(u),
]
),
v_range=[0, TAU],
u_range=[-PI / 2, PI / 2],
checkerboard_colors=[BLUE_D, BLUE_E],
resolution=(15, 32),
)
self.add(axes, sphere)
self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES)
self.move_camera(zoom=1.5)
self.move_camera(zoom=0.5)
self.wait()
運行效果:
5. 總結回顧
本篇介紹從另一種角度來實現動畫的方式,也就是不改變物體本身,而是改變觀察物體的方式。
manim
中能夠操作相機的類主要有:
- MovingCameraScene:改變相機的焦點和視野
- ZoomedScene:增加多個相機,多個相機可以從不同的視角同時觀察物體
- ThreeDScene:3D場景下的相機操作
本文關聯的微信視頻號短視頻: