灵飞猫 發表於 2025-9-26 15:16:00

Manim实现气泡特效

<p>本文将介绍如何使用<code>Manim</code>框架实现一个简单而实用的气泡特效,该特效可用于多种场景,如背景装饰、数据可视化过渡等。</p>
<h1 id="1-实现原理">1. 实现原理</h1>
<p>气泡特效的核心在于<code>BubbleEffect</code>类,它继承自Manim的<code>Animation</code>类,通过重写关键方法来实现气泡的上升、变大和透明度变化效果。</p>
<h2 id="11-核心类结构">1.1. 核心类结构</h2>
<p><code>BubbleEffect</code>类的基本结构如下:</p>
<pre><code class="language-python">class BubbleEffect(Animation):
    """
    彩色气泡特效动画类
    继承自Animation类,用于创建彩色气泡上升、变大、透明度变化的效果
    """

    def __init__(
      self,
      bubble_count=25,# 气泡数量
      bubble_size_range=(0.1, 0.5),# 气泡大小范围
      rise_speed_range=(0.6, 2.2),# 上升速度范围
      growth_rate_range=(0.005, 0.015),# 生长速度范围
      fade_rate_range=(0.02, 0.06),# 消失速度范围
      colors=None,# 气泡颜色列表
      **kwargs
    ):
      # 初始化代码...

    def create_bubble(self):
      # 创建单个气泡的代码...

    def interpolate_mobject(self, alpha):
      # 控制气泡动画效果的核心代码...
</code></pre>
<h2 id="12-气泡创建机制">1.2. 气泡创建机制</h2>
<p>在<code>__init__</code>方法中,我们首先定义了一系列参数,如气泡数量、大小范围、上升速度等,然后创建一个<code>VGroup</code>来存放所有气泡:</p>
<pre><code class="language-python"># 创建气泡组
self.bubbles = VGroup()
self.bubble_count = bubble_count
self.bubble_size_range = bubble_size_range
self.rise_speed_range = rise_speed_range
self.growth_rate_range = growth_rate_range
self.fade_rate_range = fade_rate_range
self.colors = colors or

# 保存运行时间,从kwargs中获取或使用默认值
self.run_time = kwargs.get("run_time", 5.0)

# 初始化气泡
for _ in range(bubble_count):
    bubble = self.create_bubble()
    self.bubbles.add(bubble)

# 调用父类初始化
super().__init__(self.bubbles, **kwargs)
</code></pre>
<p>每个气泡通过<code>create_bubble</code>方法创建,该方法随机设置气泡的大小、颜色和初始位置,并为每个气泡分配独立的上升速度、生长速度和消失速度:</p>
<pre><code class="language-python">def create_bubble(self):
    """创建单个彩色气泡"""
    # 随机大小
    size = random.uniform(*self.bubble_size_range)
    # 随机颜色
    color = random.choice(self.colors)
    # 创建圆形气泡
    bubble = Circle(radius=size, color=color, fill_opacity=0.4, stroke_width=2)

    # 随机初始位置(底部区域)
    x_pos = random.uniform(-config.frame_width / 2 + 1, config.frame_width / 2 - 1)
    y_pos = random.uniform(-config.frame_height / 2, -config.frame_height / 2 + 2)
    bubble.move_to()

    # 存储气泡属性
    bubble.rise_speed = random.uniform(*self.rise_speed_range)
    bubble.growth_rate = random.uniform(*self.growth_rate_range)
    bubble.fade_rate = random.uniform(*self.fade_rate_range)
    bubble.initial_radius = size

    return bubble
</code></pre>
<h2 id="13-动画插值实现">1.3. 动画插值实现</h2>
<p>动画的核心在于<code>interpolate_mobject</code>方法,它控制着每个气泡在每一帧的状态变化:</p>
<pre><code class="language-python">def interpolate_mobject(self, alpha):
    """插值函数,控制彩色气泡的动画效果"""
    dt = 1 / config.frame_rate# 每帧的时间间隔
    for bubble in self.bubbles:
      # 上升
      bubble.shift(UP * bubble.rise_speed * dt)

      # 变大
      bubble.scale(1 + bubble.growth_rate * dt)

      # 透明度变化
      current_opacity = bubble.get_fill_opacity()
      new_opacity = current_opacity - bubble.fade_rate * dt

      # 如果气泡超出屏幕顶部或透明度降到0以下,则重置
      if new_opacity &lt;= 0 or bubble.get_y() &gt; config.frame_height / 2:
            # 重置气泡
            x_pos = random.uniform(
                -config.frame_width / 2 + 1, config.frame_width / 2 - 1
            )
            y_pos = random.uniform(
                -config.frame_height / 2, -config.frame_height / 2 + 2
            )
            bubble.move_to()
            bubble.set_fill(opacity=0.4)
            bubble.set_stroke(opacity=0.4)
      else:
            bubble.set_fill(opacity=new_opacity)
            bubble.set_stroke(opacity=new_opacity)
</code></pre>
<p>这个方法实现了三个关键效果:</p>
<ol>
<li><strong>上升</strong>:每个气泡以自己的速度向上移动</li>
<li><strong>变大</strong>:每个气泡以自己的速度缓慢变大</li>
<li><strong>透明度变化</strong>:每个气泡逐渐变得透明</li>
</ol>
<p>特别值得注意的是,当气泡超出屏幕顶部或透明度降到0以下时,代码会将气泡重置到底部,从而实现循环不断的气泡效果。</p>
<h1 id="2-使用示例">2. 使用示例</h1>
<p>代码提供了两个使用示例,分别展示了普通气泡效果和彩色气泡效果。</p>
<h2 id="21-普通气泡效果">2.1. 普通气泡效果</h2>
<p><code>SimpleBubbleEffectExample</code>类展示了如何创建灰度的气泡效果:</p>
<pre><code class="language-python">class SimpleBubbleEffectExample(Scene):
    """普通气泡特效示例场景"""

    def construct(self):
      # 创建标题
      title = Text("普通气泡特效演示", font_size=48)
      title.to_edge(UP)
      self.play(Write(title))
      self.wait(0.5)

      bubble_effect = BubbleEffect(
            bubble_count=25,
            colors=,# 设置为灰色
            bubble_size_range=(0.1, 0.5),
            rise_speed_range=(0.6, 2.2),
            growth_rate_range=(0.1, 0.5),
            fade_rate_range=(0.02, 0.06),
            run_time=2,# 使用run_time而不是duration
      )

      # 播放气泡特效
      self.play(bubble_effect)
      self.wait()
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/83005/202509/83005-20250926151547740-549344047.gif" alt="" loading="lazy"></p>
<h2 id="22-彩色气泡效果">2.2. 彩色气泡效果</h2>
<p><code>ColorfulBubbleEffectExample</code>类展示了如何创建彩色的气泡效果:</p>
<pre><code class="language-python">class ColorfulBubbleEffectExample(Scene):
    """彩色气泡特效示例场景"""

    def construct(self):
      # 创建标题
      title = Text("彩色气泡特效演示", font_size=48)
      title.to_edge(UP)
      self.play(Write(title))
      self.wait(0.5)

      # 创建彩色气泡特效动画
      bubble_effect = BubbleEffect(
            bubble_count=25,
            bubble_size_range=(0.1, 0.5),
            rise_speed_range=(0.6, 2.2),
            growth_rate_range=(0.1, 0.5),
            fade_rate_range=(0.02, 0.06),
            run_time=2,# 使用run_time而不是duration
      )

      # 播放彩色气泡特效
      self.play(bubble_effect)
      self.wait()
</code></pre>
<p>两者的主要区别在于<code>SimpleBubbleEffectExample</code>显式指定了<code>colors=</code>,而<code>ColorfulBubbleEffectExample</code>则使用了默认的彩色列表。</p>
<p><img src="https://img2024.cnblogs.com/blog/83005/202509/83005-20250926151547732-1165075069.gif" alt="" loading="lazy"></p>
<h2 id="23-自定义参数">2.3. 自定义参数</h2>
<p><code>BubbleEffect</code>类提供了多个参数,可以根据需要进行调整:</p>
<table>
<thead>
<tr>
<th>参数名</th>
<th>类型</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>bubble_count</td>
<td>int</td>
<td>25</td>
<td>气泡数量</td>
</tr>
<tr>
<td>bubble_size_range</td>
<td>tuple</td>
<td>(0.1, 0.5)</td>
<td>气泡大小范围</td>
</tr>
<tr>
<td>rise_speed_range</td>
<td>tuple</td>
<td>(0.6, 2.2)</td>
<td>气泡上升速度范围</td>
</tr>
<tr>
<td>growth_rate_range</td>
<td>tuple</td>
<td>(0.005, 0.015)</td>
<td>气泡生长速度范围</td>
</tr>
<tr>
<td>fade_rate_range</td>
<td>tuple</td>
<td>(0.02, 0.06)</td>
<td>气泡透明度变化速度范围</td>
</tr>
<tr>
<td>colors</td>
<td>list</td>
<td></td>
<td>气泡颜色列表</td>
</tr>
<tr>
<td>run_time</td>
<td>float</td>
<td>5.0</td>
<td>动画运行时间</td>
</tr>
</tbody>
</table>
<p>通过调整这些参数,可以创建各种不同风格的气泡效果。</p>
<h1 id="3-总结">3. 总结</h1>
<h2 id="31-特效特点">3.1. 特效特点</h2>
<ol>
<li><strong>可定制性强</strong>:通过调整多种参数,可以创建不同风格的气泡效果</li>
<li><strong>性能优化</strong>:使用VGroup统一管理气泡,方便添加和删除</li>
<li><strong>循环动画</strong>:气泡消失后会自动重置,实现循环不断的效果</li>
<li><strong>随机性</strong>:每个气泡的大小、位置、速度等属性都是随机的,创建丰富多变的视觉效果</li>
<li><strong>统一控制</strong>:作为Animation的子类,可以与Manim的其他动画无缝集成</li>
</ol>
<h2 id="32-使用场景">3.2. 使用场景</h2>
<ol>
<li><strong>背景装饰</strong>:为视频或演示添加动态背景</li>
<li><strong>转场效果</strong>:在不同场景或章节之间作为过渡效果</li>
<li><strong>数据可视化</strong>:与数据展示结合,增强视觉吸引力</li>
<li><strong>节日氛围</strong>:通过调整颜色,可以创建适合不同节日的氛围效果</li>
<li><strong>教学辅助</strong>:在物理课上演示浮力原理,或在化学课上模拟气泡反应</li>
</ol>
<p>这个气泡特效实现简单但效果出色,可以为各种Manim动画项目增添生动的视觉元素。</p><br><br>
来源:https://www.cnblogs.com/wang_yb/p/19113551
頁: [1]
查看完整版本: Manim实现气泡特效