Manim实现水波纹特效

本文将介绍如何使用ManimCE框架实现一个水波纹特效,让你的数学动画更加生动有趣。

1. 实现原理

水波纹特效通过WaterRipple类实现,这是一个自定义的Animation子类。让我们从代码角度来分析其实现原理:

1.1. 核心数据结构

python 复制代码
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类采用了以下核心设计:

  1. 波纹数据结构 :使用Annulus(圆环)作为基本波纹单元,通过self.ripples列表存储多个波纹对象
  2. 颜色处理:支持单一颜色或渐变色列表,自动处理颜色不足时的循环使用
  3. 场景集成 :提供可选的scene参数,方便将波纹直接添加到场景中

1.2. 动画插值算法

动画的核心在于interpolate_mobject方法,它定义了动画如何随时间变化:

python 复制代码
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)

这里的关键技术点包括:

  1. 相位偏移:通过为每个波纹分配不同的相位偏移,创造出波纹依次扩散的视觉效果
  2. 正弦函数插值:使用正弦函数控制透明度变化,实现更自然的淡出效果
  3. 动态更新 :在每一帧都创建新的Annulus对象并通过become()方法更新波纹的状态

1.3. 资源清理机制

动画结束后,需要清理创建的波纹对象:

python 复制代码
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. 单个水波纹效果

python 复制代码
# 示例场景:单个水波纹效果
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. 使用步骤详解

  1. 准备工作:首先导入必要的库
python 复制代码
from manim import *
import numpy as np
  1. 创建中心点:水波纹效果需要一个中心点作为扩散起点
python 复制代码
center_point = ORIGIN
center_dot = Dot(center_point, color=BLUE, radius=0.1)
self.play(FadeIn(center_dot))
  1. 定义颜色方案:可以使用渐变色列表增强视觉效果
python 复制代码
gradient_colors = [BLUE, TEAL, GREEN, YELLOW, RED]
  1. 应用水波纹动画 :配置各项参数并播放动画
    • 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. 特效特点

  1. 视觉效果丰富:支持单一颜色和渐变色,可创建多种视觉风格
  2. 高度可定制:提供多个参数调整波纹数量、大小、速度和颜色
  3. 实现简洁:基于Manim的Animation类扩展,代码结构清晰易懂
  4. 资源管理完善:包含清理机制,避免场景对象堆积

3.2. 使用场景

水波纹特效在以下场景中特别适用:

  1. 几何演示:用于展示圆的概念、扩散过程等几何知识
  2. 受力分析:模拟波的传播,展示力学中的波动现象
  3. 交互反馈:作为点击或其他交互操作的视觉反馈
  4. 强调重点:用于强调画面中的特定元素或区域
  5. 过渡效果:作为场景切换或元素出现/消失的过渡动画

通过这个简单但功能强大的水波纹特效,可以为你的数学动画增添更多视觉吸引力和专业感。无论是教学演示、科学解释还是艺术创作,都能发挥重要作用。

相关推荐
2401_8315017315 分钟前
Python学习之Day07-08学习(Django网页Web开发)
python·学习·django
IT_陈寒25 分钟前
Redis性能翻倍秘籍:10个99%开发者不知道的冷门配置优化技巧
前端·人工智能·后端
Tiny番茄30 分钟前
leetcode 3. 无重复字符的最长子串
数据结构·python·算法·leetcode
洛小豆33 分钟前
Swagger3学习与实践指南
spring boot·后端·spring cloud
Victor35642 分钟前
Redis(58)如何配置和查看Redis的慢查询日志?
后端
Victor35644 分钟前
Redis(59)Redis的主从复制是如何实现的?
后端
胡斌附体1 小时前
离线docker安装jupyter(python网页版编辑器)
python·docker·jupyter·image·tar·save
摇滚侠2 小时前
Spring Boot 3零基础教程,自动配置机制,笔记07
spring boot·笔记·后端
java1234_小锋2 小时前
TensorFlow2 Python深度学习 - TensorFlow2框架入门 - 使用Keras实现逻辑回归
python·深度学习·tensorflow·tensorflow2
java1234_小锋2 小时前
TensorFlow2 Python深度学习 - TensorFlow2框架入门 - Sequential顺序模型
python·深度学习·tensorflow·tensorflow2