Manim實(shí)現(xiàn)漣漪擴(kuò)散特效
在視頻制作和數(shù)據(jù)可視化領(lǐng)域,漣漪擴(kuò)散特效是一種常見(jiàn)且富有視覺(jué)吸引力的動(dòng)畫(huà)效果。
本文將詳細(xì)介紹如何使用Manim數(shù)學(xué)動(dòng)畫(huà)引擎來(lái)實(shí)現(xiàn)這一效果,包括其實(shí)現(xiàn)原理、使用示例以及應(yīng)用場(chǎng)景。
1. 實(shí)現(xiàn)原理
漣漪擴(kuò)散特效主要通過(guò)RippleEffect類(lèi)來(lái)實(shí)現(xiàn),該類(lèi)繼承自Manim的Animation基類(lèi)。讓我們深入了解其核心實(shí)現(xiàn)機(jī)制:
1.1. 核心設(shè)計(jì)思路
class RippleEffect(Animation):
"""
漣漪擴(kuò)散特效動(dòng)畫(huà)類(lèi)
實(shí)現(xiàn)方法:使用Circle類(lèi)創(chuàng)建多個(gè)同心圓,然后通過(guò)發(fā)光層實(shí)現(xiàn)發(fā)光效果,
再利用脈沖效果實(shí)現(xiàn)閃爍,從而模擬漣漪的擴(kuò)散和閃爍。
"""
1.2. 參數(shù)設(shè)計(jì)
該類(lèi)提供了豐富的參數(shù)控制,使其具有高度可定制性:
def __init__(
self,
mobject: Mobject,
num_ripples: int = 5,
max_radius: float = 3.0,
min_radius: float = 0.1,
ripple_speed: float = 1.0,
color: ParsableManimColor = BLUE,
fade_out: bool = True,
glow_num: int = 3,
glow_width: float = 5,
pulse_frequency: float = 2.0,
**kwargs
):
# 存儲(chǔ)參數(shù)
self.num_ripples = num_ripples
self.max_radius = max_radius
self.min_radius = min_radius
self.ripple_speed = ripple_speed
self.color = color
self.fade_out = fade_out
self.glow_num = glow_num
self.glow_width = glow_width
self.pulse_frequency = pulse_frequency
1.3. 多顏色支持實(shí)現(xiàn)
代碼巧妙地支持單色和多色兩種模式:
# 處理顏色參數(shù),支持單個(gè)顏色或多個(gè)顏色
if isinstance(color, (list, tuple)):
self.colors = list(color)
self.use_multiple_colors = True
else:
self.colors = [color]
self.use_multiple_colors = False
1.4. 漣漪對(duì)象初始化
在構(gòu)造函數(shù)中,代碼預(yù)先創(chuàng)建了所有需要的漣漪圓環(huán)和對(duì)應(yīng)的發(fā)光層:
# 創(chuàng)建漣漪圓環(huán)列表
self.ripples = []
self.glow_layers = []
# 創(chuàng)建多個(gè)同心圓環(huán)作為漣漪
for i in range(num_ripples):
# 確定當(dāng)前漣漪的顏色
if self.use_multiple_colors:
ripple_color = self.colors[i % len(self.colors)]
else:
ripple_color = self.colors[0]
# 使用Circle創(chuàng)建圓環(huán),初始半徑為最小半徑
circle = Circle(
radius=min_radius,
stroke_color=ripple_color,
stroke_width=2,
fill_opacity=0,
).move_to(mobject.get_center())
self.ripples.append(circle)
# 為每個(gè)漣漪創(chuàng)建發(fā)光層
glow_group = []
for j in range(glow_num):
glow = circle.copy()
glow_group.append(glow)
self.glow_layers.append(glow_group)
1.5. 動(dòng)畫(huà)插值實(shí)現(xiàn)
interpolate_mobject方法是實(shí)現(xiàn)動(dòng)畫(huà)效果的核心,它在每一幀都會(huì)被調(diào)用:
def interpolate_mobject(self, alpha: float):
"""
實(shí)現(xiàn)動(dòng)畫(huà)效果的核心方法
Parameters:
alpha - 是一個(gè)介于 0 和 1 之間的參數(shù),表示動(dòng)畫(huà)的進(jìn)度
"""
# 計(jì)算時(shí)間進(jìn)度,考慮漣漪速度
time_alpha = alpha * self.ripple_speed
# 為每個(gè)漣漪計(jì)算不同的相位偏移,創(chuàng)建連續(xù)的漣漪效果
for i, (ripple, glow_group) in enumerate(zip(self.ripples, self.glow_layers)):
# 確定當(dāng)前漣漪的顏色
if self.use_multiple_colors:
ripple_color = self.colors[i % len(self.colors)]
else:
ripple_color = self.colors[0]
# 計(jì)算每個(gè)漣漪的相位偏移
phase_offset = i / self.num_ripples
# 計(jì)算當(dāng)前漣漪的時(shí)間進(jìn)度
ripple_time = (time_alpha + phase_offset) % 1
# 計(jì)算當(dāng)前半徑,從最小半徑到最大半徑
current_radius = interpolate(self.min_radius, self.max_radius, ripple_time)
# 計(jì)算透明度,如果啟用淡出效果
if self.fade_out:
# 使用正弦函數(shù)創(chuàng)建自然的淡出效果
opacity = np.sin(ripple_time * PI) * 0.8
else:
opacity = 0.8
# 確保透明度不為負(fù)數(shù)
opacity = max(0, opacity)
# 添加脈沖效果
pulse_effect = np.sin(ripple_time * self.pulse_frequency * 2 * PI) * 0.2
opacity = max(0, opacity + pulse_effect)
# 創(chuàng)建新的圓環(huán)并更新屬性
new_ripple = Circle(
radius=current_radius,
stroke_color=ripple_color,
stroke_width=2,
stroke_opacity=opacity,
fill_opacity=0,
).move_to(self.mobject.get_center())
# 更新漣漪對(duì)象
ripple.become(new_ripple)
# 更新發(fā)光層
for j, glow in enumerate(glow_group):
phase = j / self.glow_num
# 設(shè)置發(fā)光層屬性
glow.become(new_ripple.copy())
glow.set_stroke(
width=self.glow_width * (1 - phase) + 1, # 寬度遞減
color=ripple_color,
opacity=opacity * 0.3 * (1 - phase), # 透明度遞減
)
這個(gè)方法實(shí)現(xiàn)了幾個(gè)關(guān)鍵的視覺(jué)效果:
- 漣漪擴(kuò)散:通過(guò)計(jì)算當(dāng)前半徑,使圓環(huán)從中心向外擴(kuò)散
- 漣漪淡出:使用正弦函數(shù)創(chuàng)建自然的淡出效果
- 脈沖效果:添加額外的正弦波動(dòng)來(lái)模擬漣漪的脈沖閃爍
- 發(fā)光效果:為每個(gè)漣漪添加多層發(fā)光效果,并使它們的寬度和透明度遞減
- 相位偏移:為不同的漣漪設(shè)置不同的相位偏移,創(chuàng)造連續(xù)的漣漪效果
2. 使用示例
代碼提供了三種不同的使用示例,展示了漣漪效果的多樣化應(yīng)用:
2.1. 單顏色漣漪效果
最簡(jiǎn)單的應(yīng)用場(chǎng)景,從一個(gè)中心點(diǎn)向外擴(kuò)散單色漣漪:
class RippleEffectExample(Scene):
"""
漣漪擴(kuò)散特效示例場(chǎng)景
"""
def construct(self):
# 創(chuàng)建一個(gè)點(diǎn)作為漣漪的中心
center_dot = Dot(color=YELLOW)
self.add(center_dot)
# 創(chuàng)建漣漪擴(kuò)散特效
ripple_effect = RippleEffect(
center_dot,
num_ripples=8,
max_radius=4.0,
min_radius=0.1,
ripple_speed=1.5,
color=BLUE,
glow_num=5,
glow_width=8,
pulse_frequency=3.0,
)
# 將所有漣漪和發(fā)光層添加到場(chǎng)景中
for ripple, glow_group in zip(ripple_effect.ripples, ripple_effect.glow_layers):
self.add(ripple)
for glow in glow_group:
self.add(glow)
# 播放動(dòng)畫(huà)
self.play(ripple_effect, run_time=5)
self.wait()

2.2. 雙漣漪效果
展示兩個(gè)同時(shí)擴(kuò)散的漣漪效果,可以用于表現(xiàn)兩個(gè)對(duì)象之間的交互:
class DualRippleEffectExample(Scene):
"""
雙漣漪擴(kuò)散特效示例場(chǎng)景
展示兩個(gè)同時(shí)擴(kuò)散的漣漪效果
"""
def construct(self):
# 創(chuàng)建兩個(gè)點(diǎn)作為漣漪的中心
center_dot1 = Dot(color=YELLOW).shift(LEFT * 2)
center_dot2 = Dot(color=RED).shift(RIGHT * 2)
self.add(center_dot1, center_dot2)
# 創(chuàng)建兩個(gè)漣漪擴(kuò)散特效
ripple_effect1 = RippleEffect(
center_dot1,
num_ripples=6,
max_radius=1.5,
min_radius=0.1,
ripple_speed=1.2,
color=BLUE,
glow_num=4,
glow_width=6,
pulse_frequency=5.5,
)
ripple_effect2 = RippleEffect(
center_dot2,
num_ripples=6,
max_radius=1.5,
min_radius=0.1,
ripple_speed=1.2,
color=RED,
glow_num=8,
glow_width=4,
pulse_frequency=2.5,
)
# 將所有漣漪和發(fā)光層添加到場(chǎng)景中
for ripple, glow_group in zip(
ripple_effect1.ripples, ripple_effect1.glow_layers
):
self.add(ripple)
for glow in glow_group:
self.add(glow)
for ripple, glow_group in zip(
ripple_effect2.ripples, ripple_effect2.glow_layers
):
self.add(ripple)
for glow in glow_group:
self.add(glow)
# 同時(shí)播放兩個(gè)動(dòng)畫(huà)
self.play(ripple_effect1, ripple_effect2, run_time=5)
self.wait()

2.3. 多顏色漣漪效果
最具視覺(jué)沖擊力的效果,從一個(gè)中心點(diǎn)向外擴(kuò)散多種顏色的漣漪:
class MultiColorRippleEffectExample(Scene):
def construct(self):
# 創(chuàng)建一個(gè)點(diǎn)作為漣漪的中心
center_dot = Dot(color=YELLOW)
self.add(center_dot)
# 創(chuàng)建漣漪擴(kuò)散特效
ripple_effect = RippleEffect(
center_dot,
num_ripples=8,
max_radius=4.0,
min_radius=0.1,
ripple_speed=1.5,
color=[BLUE, RED, GREEN, YELLOW, ORANGE],
glow_num=5,
glow_width=8,
pulse_frequency=3.0,
)
# 將所有漣漪和發(fā)光層添加到場(chǎng)景中
for ripple, glow_group in zip(ripple_effect.ripples, ripple_effect.glow_layers):
self.add(ripple)
for glow in glow_group:
self.add(glow)
# 播放動(dòng)畫(huà)
self.play(ripple_effect, run_time=5)
self.wait()

3. 總結(jié)
3.1. 特效特點(diǎn)
- 高度可定制:提供了豐富的參數(shù)控制,包括漣漪數(shù)量、大小、速度、顏色、發(fā)光效果等
- 視覺(jué)效果優(yōu)美:通過(guò)多層發(fā)光、脈沖效果和相位偏移,創(chuàng)造出逼真而華麗的漣漪效果
- 支持多顏色模式:可以實(shí)現(xiàn)單色漣漪或彩虹般的多色漣漪效果
- 易于擴(kuò)展:基于Manim的Animation類(lèi),易于與其他動(dòng)畫(huà)效果結(jié)合
3.2. 使用場(chǎng)景
漣漪擴(kuò)散特效在以下場(chǎng)景中特別有用:
- 數(shù)據(jù)可視化:用于突出顯示數(shù)據(jù)點(diǎn)或數(shù)據(jù)變化
- 科學(xué)動(dòng)畫(huà):模擬水面波紋、聲波、電磁波等物理現(xiàn)象
- 教育視頻:在解釋概念時(shí)吸引觀眾注意力,提高學(xué)習(xí)效果
- 產(chǎn)品展示:為產(chǎn)品演示添加視覺(jué)亮點(diǎn),增強(qiáng)吸引力
- 片頭片尾:作為視頻過(guò)渡或裝飾元素
- 用戶(hù)界面設(shè)計(jì):在交互式應(yīng)用中提供視覺(jué)反饋
通過(guò)本文介紹的RippleEffect類(lèi),你可以輕松在自己的動(dòng)畫(huà)項(xiàng)目中實(shí)現(xiàn)這一效果,為你的作品增添視覺(jué)吸引力。

浙公網(wǎng)安備 33010602011771號(hào)