Manim实现闪光轨迹特效

在动画制作中,轨迹特效常常用于增强视觉效果,而带有闪光效果的轨迹更是能够吸引观众的注意力。

本文将介绍如何使用Manim动画库实现闪光轨迹特效。

1. 实现原理

下面的GlowingTracedPath类参考了Manim中的TracePath类,增加了闪光和渐变色的效果。

python 复制代码
class GlowingTracedPath(VMobject):
    def __init__(
        self,
        traced_point_func: Callable,
        stroke_width: float = 2,
        stroke_color: ParsableManimColor | None = WHITE,
        dissipating_time: float | None = None,
        gradient_colors: list[ParsableManimColor] | None = None,  #
        glow_speed: int = 2,
        **kwargs,
    ):
        """
        构造函数

        Parameters:
            traced_point_func - 回调函数,用于获取被追踪点的当前位置
            stroke_width - 轨迹的宽度,默认为 2
            stroke_color - 轨迹的基本颜色,默认为白色
            dissipating_time - 轨迹的消散时间
            gradient_colors - 颜色渐变列表
            glow_speed - 闪光速度,控制轨迹闪光效果的快慢
            **kwargs - 用于传递额外的关键字参数到父类VMobject的构造函数中
        """
        super().__init__(
            stroke_color=stroke_color,
            stroke_width=stroke_width,
            **kwargs,
        )
        self.glow_speed = glow_speed

        if not gradient_colors is None:
            self.set_color_by_gradient(gradient_colors)

        self.set_stroke(opacity=0.2)

        self.traced_point_func = traced_point_func
        self.dissipating_time = dissipating_time
        self.time = 1

        self.add_updater(self.update_path)

    def update_path(self, mob, dt):
        # 更新轨迹中的点
        new_point = self.traced_point_func()
        if not self.has_points():
            self.start_new_path(new_point)

        self.time += dt
        t = self.time * self.glow_speed  # 控制脉冲速度
        intensity = 0.25 * np.sin(t) + 0.75  # 0.5-1之间波动
        # 动态调整透明度
        self.set_stroke(
            opacity=intensity,  # 透明度波动
        )

        self.add_line_to(new_point)
        # 轨迹消散
        if self.dissipating_time:
            if self.time - 1 > self.dissipating_time:
                nppcc = self.n_points_per_curve
                self.set_points(self.points[nppcc:])

初始化函数(__init__)的参数,代码中已经有详细的注释,不再赘述。

至于更新轨迹的update_path方法,它的关键逻辑有:

  • 获取新点 :通过traced_point_func获取被追踪点的当前位置,并将其添加到轨迹的末尾
  • 动态调整透明度 :使用正弦函数np.sin生成一个在0.51之间波动的强度值intensity,并通过set_stroke方法动态调整轨迹的透明度,从而实现闪烁效果
  • 轨迹消散 :如果设置了dissipating_time参数,当轨迹的持续时间超过该值时,会移除轨迹的起始部分,使轨迹逐渐消失

此外,GlowingTracedPath类还会通过set_color_by_gradient方法为轨迹设置颜色渐变效果。

2. 使用示例

接下来我们通过几个示例来看看如何使用这个特效。

2.1. 渐变色轨迹

基于上面我们实现的GlowingTracedPath类,实现一个渐变色的轨迹非常简单。

python 复制代码
a = Dot(RIGHT * 2)
b = GlowingTracedPath(
    a.get_center,
    gradient_colors=[BLUE, RED, YELLOW],
)
self.add(a, b)
self.play(a.animate(path_arc=PI / 2).shift(LEFT * 2), run_time=2)
self.play(a.animate(path_arc=-PI / 2).shift(LEFT * 2), run_time=2)

代码中,轨迹b 追踪点a 的位置,形成一个由参数gradient_colors指定的渐变色轨迹。

2.2. 轨迹逐渐消失

上面的示例中,轨迹不会消失,通过参数dissipating_time,可以指定轨迹存在的时间(单位:秒)。

python 复制代码
b = GlowingTracedPath(
    a.get_center,
    gradient_colors=[BLUE, RED, YELLOW],
    dissipating_time=0.5,
)

轨迹bdissipating_time设置为0.5,也就是新产生的轨迹会在0.5秒后逐渐消失。

2.3. 轨迹闪烁

最后,来看看轨迹的闪光效果,下面的通过设置两种不同的glow_speed(闪烁的速度),

来比较不同速度下的闪烁效果。

python 复制代码
a1 = Dot()
a2 = Dot()
b1 = GlowingTracedPath(
    a1.get_center,
    gradient_colors=[BLUE, RED, YELLOW],
    glow_speed=8,
)
b2 = GlowingTracedPath(
    a2.get_center,
    gradient_colors=[BLUE, RED, YELLOW],
    glow_speed=16,
)
self.add(a1, b1, a2, b2)

heart1 = ImplicitFunction(
    lambda x, y: (x**2 + y**2 - 1) ** 3 - x**2 * y**3,
    color=PINK,
    x_range=[-1.5, 1.5],
    y_range=[-1.2, 1.8],
).shift(LEFT * 1.5)
heart2 = ImplicitFunction(
    lambda x, y: (x**2 + y**2 - 1) ** 3 - x**2 * y**3,
    color=PINK,
    x_range=[-1.5, 1.5],
    y_range=[-1.2, 1.8],
).shift(RIGHT * 1.5)

self.play(MoveAlongPath(a1, heart1), MoveAlongPath(a2, heart2), run_time=4)

左边 的心形glow_speed=8右边 的心形glow_speed=16,所以右边的闪烁速度会快一些。

3. 总结

通过GlowingTracedPath类,我们可以轻松地在Manim中实现带有闪光效果的轨迹。

这个类通过动态调整透明度和颜色渐变,结合轨迹的实时更新,创造出了引人注目的视觉效果。

无论是用于数学动画还是其他创意项目,这种特效都能为你的作品增添独特的魅力。

相关推荐
武子康2 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在2 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net
文心快码BaiduComate3 小时前
文心快码入选2025服贸会“数智影响力”先锋案例
前端·后端·程序员
neoooo3 小时前
🌐 Cloudflare Tunnel vs ZeroTier:两个世界的内网穿透哲学
后端
Juchecar3 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
涡能增压发动积3 小时前
当你不了解“异步”时请慎用“异步”——记一次生产环境故障排查之旅
后端
文心快码BaiduComate3 小时前
用Comate Zulu开发一款微信小程序
前端·后端·微信小程序
用户8356290780513 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_3 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi