Manim实现线条发光效果

在动画制作中,发光效果是一种非常吸引眼球的视觉元素,它可以为简单的线条增添动态和活力。

今天,我们将通过Manim框架来实现一个线条的发光效果,并逐步解析代码,让你轻松掌握这个技巧。

准备工作

首先确保安装Manim社区版(ManimCE):

bash 复制代码
pip install manim

实现的思路

要让线条发光,我们需要在基础线条的周围添加一层层的**"发光层"**,并通过动态调整这些发光层的透明度和宽度,来模拟发光的效果。

主要思路和步骤如下:

  1. 创建基础线条:首先绘制一条普通的线条作为发光的基础。
  2. 添加发光层:在基础线条的周围添加多层线条,这些线条将作为发光效果的载体。
  3. 动态调整发光层属性:通过正弦波函数动态调整发光层的透明度和宽度,使其产生闪烁的发光效果。

实现的过程

按照实现的思路,下面逐步来实现:

创建基础线条

python 复制代码
class PulsingGlowLine(Scene):
    def construct(self):
        # 创建基础直线
        line = Line(LEFT, RIGHT, color=BLUE, stroke_width=2).scale(3)
        line.set_stroke(width=2)

        # 第一阶段:绘制基础直线
        self.play(Create(line))
        self.wait(0.5)

其中代码主要含义:

  • Line(LEFT, RIGHT, color=BLUE, stroke_width=2):创建了一条从左到右的蓝色线条,宽度为2。
  • .scale(3):将线条放大3倍,使其更明显。
  • self.play(Create(line)):使用 Create 动画将线条绘制到场景中。
  • self.wait(0.5):暂停0.5秒,让用户有时间看清基础线条。

添加发光层

python 复制代码
        # 创建发光效果组
        glow_group = VGroup()
        colors = [BLUE_A, BLUE_E, RED_A, RED_E]  # 发光颜色序列
        num_layers = 12  # 发光层数量

        # 创建多层发光效果
        for i in range(num_layers):
            glow = line.copy()
            phase = i / num_layers  # 相位控制

            # 设置发光层属性
            glow.set_stroke(
                width=5 * (1 - phase) + 2,  # 宽度递减
                color=colors[i % len(colors)],
                opacity=0,  # 初始完全透明
            )
            glow_group.add(glow)

其中代码主要含义:

  • VGroup():是一个组合对象,用于管理多个图形对象。
  • colors:是一个颜色列表,用于为发光层指定不同的颜色。
  • num_layers:定义了发光层的数量。
  • 在循环中:通过 line.copy() 复制基础线条,并调整其宽度、颜色和透明度。
  • width=5 * (1 - phase) + 2:使发光层的宽度从外到内逐渐减小。
  • opacity=0:将发光层的初始透明度设置为完全透明,后续通过动态调整透明度来实现发光效果。

动态调整发光层属性

python 复制代码
        # 将发光层放在基础线下方
        glow_group.set_z_index(line.z_index - 1)
        self.add(glow_group, line)
        self.wait()

        # 定义更新函数实现脉冲效果
        def update_glow(group, dt):
            # 使用正弦波生成动态参数
            t = self.time * 2  # 控制脉冲速度
            for i, glow in enumerate(group):
                phase = i * 0.15  # 相位偏移量
                intensity = (np.sin(t + phase) + 1) / 2  # 0-1之间波动

                # 动态调整属性
                glow.set_stroke(
                    opacity=intensity * 0.5,  # 透明度波动
                    width=5 * intensity + 2,  # 宽度波动
                )

        # 添加持续更新器
        glow_group.add_updater(update_glow)
        self.wait(6)  # 展示6秒动态效果

其中代码主要含义:

  • glow_group.set_z_index(line.z_index - 1):将发光层放在基础线条的下方,避免遮挡基础线条。
  • update_glow:是一个更新函数,用于动态调整发光层的属性。
  • self.time:是ManimCE内置的时间变量,表示动画播放的时间。
  • np.sin(t + phase):生成一个在-1到1之间波动的值,通过(np.sin(t + phase) + 1) / 2 将其转换为0到1之间的值,作为发光强度intensity。
  • glow.set_stroke(opacity=intensity * 0.5, width=5 * intensity + 2):动态调整发光层的透明度和宽度,使其产生闪烁的效果。
  • glow_group.add_updater(update_glow):将更新函数绑定到发光层组,使其在动画播放过程中持续更新。
  • self.wait(6):让动画展示6秒的发光效果。

结束动画

python 复制代码
        # 移除更新器并保持最终状态
        glow_group.remove_updater(update_glow)
        self.remove(glow_group)
        self.wait()

代码主要含义:

  • glow_group.remove_updater(update_glow):移除更新函数,停止发光效果的动态变化。
  • self.remove(glow_group):将发光层组从场景中移除。
  • self.wait():暂停动画,等待用户手动停止。

整个代码运行效果如下:

总结

通过这个文章,我们可以了解到:

  1. 发光效果 = 多层半透明描边 + 动态属性变化
  2. add_updater实现持续动画
  3. 三角函数创造平滑波动
  4. 相位差产生波浪效果

现在尝试修改参数创建你自己的特效吧!

比如,修改发光的颜色,发光的脉冲频率等等。

相关推荐
wang_yb13 小时前
使用命令行做描述性统计的技巧
数据分析·databook
zwd20051 天前
Manim 竖屏 1080×1920 配置详解:pixel_width、frame_width 怎么写(0.21.0 / 0.22.0 实测)
python·manim·数学动画·短视频制作·manim教程·竖屏视频
zwd20054 天前
Manim 画布尺寸与像素换算详解:frame_width、frame_height、pixel_width 和画质参数(0.21.0 实测)
python·分辨率·manim·数学动画·frame_width·manim教程
wang_yb4 天前
MinMax vs Standard vs Robust:三种特征缩放怎么选
ai·数据分析·databook
wang_yb6 天前
用 Pydantic AI 从零搭建一个能干活的 AI Agent
ai·databook
wang_yb7 天前
从循环到向量化:NumPy提速的7个关键思维
数据分析·databook
wang_yb9 天前
ManimCE v0.22.0 发布:输出配置大一统与渲染流程重构
databook·manim
wang_yb11 天前
Scikit-Learn实战:5步搞定PCA降维
ai·databook
zwd200512 天前
Manim add_sound 用法详解:time_offset、gain、多条音频与旁白对齐(2026 最新教程,0.21.0)
python·音频·动画·manim·数学动画·add_sound
wang_yb13 天前
什么是范数?用 NumPy 动手算一遍就明白了
数据分析·databook