Manim實現水波紋特效
本文將介紹如何使用ManimCE框架實現一個水波紋特效,讓你的數學動畫更加生動有趣。
1. 實現原理
水波紋特效通過WaterRipple類實現,這是一個自定義的Animation子類。讓我們從代碼角度來分析其實現原理:
1.1. 核心數據結構
class WaterRipple(Animation):
def __init__(
self, mobject, scene=None, num_ripples=5, max_outer_radius=3,
min_inner_radius=1, run_time=2, wave_speed=1.0,
color=BLUE, fade_out=True, **kwargs
):
# 初始化參數設置
self.num_ripples = num_ripples
self.max_outer_radius = max_outer_radius
self.min_inner_radius = min_inner_radius
self.wave_speed = wave_speed
self.color = color
self.fade_out = fade_out
self.ripples = []
self.mobject = mobject
self.scene = scene
# 顏色處理邏輯
self.color_list = color if isinstance(color, list) else [color] * num_ripples
if len(self.color_list) < num_ripples:
self.color_list = self.color_list * (
num_ripples // len(self.color_list) + 1
)
self.color_list = self.color_list[:num_ripples]
# 創建波紋對象
for i in range(num_ripples):
c = Annulus(
inner_radius=0, outer_radius=0,
color=self.color_list[i], stroke_width=2, fill_opacity=0,
)
c.move_to(mobject.get_center())
self.ripples.append(c)
# 將波紋添加到場景
if self.scene is not None:
for ripple in self.ripples:
self.scene.add(ripple)
super().__init__(mobject, run_time=run_time, **kwargs)
從代碼中可以看出,WaterRipple類采用了以下核心設計:
- 波紋數據結構:使用
Annulus(圓環)作為基本波紋單元,通過self.ripples列表存儲多個波紋對象 - 顏色處理:支持單一顏色或漸變色列表,自動處理顏色不足時的循環使用
- 場景集成:提供可選的
scene參數,方便將波紋直接添加到場景中
1.2. 動畫插值算法
動畫的核心在于interpolate_mobject方法,它定義了動畫如何隨時間變化:
def interpolate_mobject(self, alpha: float) -> None:
# 計算每個波紋的半徑和透明度
for i in range(self.num_ripples):
# 每個波紋有不同的相位偏移
phase_offset = i * (np.pi / self.num_ripples)
# 使用正弦函數計算半徑和透明度,實現波動效果
time_progress = (alpha + phase_offset * 0.2) % 1
radius = self.max_outer_radius * time_progress
if self.fade_out:
# 透明度隨半徑增大而減小,使用正弦函數使淡出更自然
opacity = max(0, np.sin(time_progress * np.pi))
else:
opacity = 1
# 應用變換,使用對應的顏色
new_c = Annulus(
inner_radius=self.min_inner_radius,
outer_radius=radius,
color=self.color_list[i],
stroke_width=2,
fill_opacity=opacity,
)
new_c.move_to(self.mobject.get_center())
self.ripples[i].become(new_c)
這里的關鍵技術點包括:
- 相位偏移:通過為每個波紋分配不同的相位偏移,創造出波紋依次擴散的視覺效果
- 正弦函數插值:使用正弦函數控制透明度變化,實現更自然的淡出效果
- 動態更新:在每一幀都創建新的
Annulus對象并通過become()方法更新波紋的狀態
1.3. 資源清理機制
動畫結束后,需要清理創建的波紋對象:
def clean_up_from_scene(self, scene: Scene) -> None:
# 動畫結束后清理波紋
for ripple in self.ripples:
if ripple in scene.mobjects:
scene.remove(ripple)
super().clean_up_from_scene(scene)
這個方法確保動畫結束后不會在場景中留下多余的對象,保持場景的整潔。
2. 使用示例
下面通過一個完整的示例場景來展示如何使用水波紋特效:
2.1. 單個水波紋效果
# 示例場景:單個水波紋效果
class Example01(Scene):
def construct(self):
# 創建中心點
center_point = ORIGIN
center_dot = Dot(center_point, color=BLUE, radius=0.1)
self.play(FadeIn(center_dot))
self.wait()
# 應用水波紋動畫,使用漸變色效果
# 創建顏色漸變列表,從藍色到紫色再到紅色
gradient_colors = [BLUE, TEAL, GREEN, YELLOW, RED]
self.play(
WaterRipple(
center_dot,
scene=self,
num_ripples=5,
max_outer_radius=2,
run_time=4,
wave_speed=1.2,
color=gradient_colors, # 使用漸變色列表
fade_out=True,
stroke_width=1,
)
)
self.wait(2)

2.2. 使用步驟詳解
- 準備工作:首先導入必要的庫
from manim import *
import numpy as np
- 創建中心點:水波紋效果需要一個中心點作為擴散起點
center_point = ORIGIN
center_dot = Dot(center_point, color=BLUE, radius=0.1)
self.play(FadeIn(center_dot))
- 定義顏色方案:可以使用漸變色列表增強視覺效果
gradient_colors = [BLUE, TEAL, GREEN, YELLOW, RED]
- 應用水波紋動畫:配置各項參數并播放動畫
center_dot:波紋中心點對象scene=self:當前場景引用num_ripples=5:波紋數量max_outer_radius=2:最大半徑run_time=4:動畫運行時間wave_speed=1.2:波紋傳播速度color=gradient_colors:使用漸變色列表fade_out=True:啟用淡出效果
2.3. 自定義參數調整
根據實際需求,可以調整以下關鍵參數以獲得不同的視覺效果:
num_ripples:控制波紋數量,更多的波紋會使效果更密集max_outer_radius:控制波紋擴散范圍min_inner_radius:控制波紋的最小內半徑run_time:控制動畫持續時間wave_speed:控制波紋傳播速度color:可以是單一顏色或漸變色列表fade_out:是否啟用淡出效果
3. 總結
3.1. 特效特點
- 視覺效果豐富:支持單一顏色和漸變色,可創建多種視覺風格
- 高度可定制:提供多個參數調整波紋數量、大小、速度和顏色
- 實現簡潔:基于Manim的Animation類擴展,代碼結構清晰易懂
- 資源管理完善:包含清理機制,避免場景對象堆積
3.2. 使用場景
水波紋特效在以下場景中特別適用:
- 幾何演示:用于展示圓的概念、擴散過程等幾何知識
- 受力分析:模擬波的傳播,展示力學中的波動現象
- 交互反饋:作為點擊或其他交互操作的視覺反饋
- 強調重點:用于強調畫面中的特定元素或區域
- 過渡效果:作為場景切換或元素出現/消失的過渡動畫
通過這個簡單但功能強大的水波紋特效,可以為你的數學動畫增添更多視覺吸引力和專業感。無論是教學演示、科學解釋還是藝術創作,都能發揮重要作用。

浙公網安備 33010602011771號