找回密码
 立即注册
首页 业界区 业界 Manim实现闪光轨迹特效

Manim实现闪光轨迹特效

吞脚 昨天 18:05
在动画制作中,轨迹特效常常用于增强视觉效果,而带有闪光效果的轨迹更是能够吸引观众的注意力。
本文将介绍如何使用Manim动画库实现闪光轨迹特效。
1. 实现原理

下面的GlowingTracedPath类参考了Manim中的TracePath类,增加了闪光和渐变色的效果。
  1. class GlowingTracedPath(VMobject):
  2.     def __init__(
  3.         self,
  4.         traced_point_func: Callable,
  5.         stroke_width: float = 2,
  6.         stroke_color: ParsableManimColor | None = WHITE,
  7.         dissipating_time: float | None = None,
  8.         gradient_colors: list[ParsableManimColor] | None = None,  #
  9.         glow_speed: int = 2,
  10.         **kwargs,
  11.     ):
  12.         """
  13.         构造函数
  14.         Parameters:
  15.             traced_point_func - 回调函数,用于获取被追踪点的当前位置
  16.             stroke_width - 轨迹的宽度,默认为 2
  17.             stroke_color - 轨迹的基本颜色,默认为白色
  18.             dissipating_time - 轨迹的消散时间
  19.             gradient_colors - 颜色渐变列表
  20.             glow_speed - 闪光速度,控制轨迹闪光效果的快慢
  21.             **kwargs - 用于传递额外的关键字参数到父类VMobject的构造函数中
  22.         """
  23.         super().__init__(
  24.             stroke_color=stroke_color,
  25.             stroke_width=stroke_width,
  26.             **kwargs,
  27.         )
  28.         self.glow_speed = glow_speed
  29.         if not gradient_colors is None:
  30.             self.set_color_by_gradient(gradient_colors)
  31.         self.set_stroke(opacity=0.2)
  32.         self.traced_point_func = traced_point_func
  33.         self.dissipating_time = dissipating_time
  34.         self.time = 1
  35.         self.add_updater(self.update_path)
  36.     def update_path(self, mob, dt):
  37.         # 更新轨迹中的点
  38.         new_point = self.traced_point_func()
  39.         if not self.has_points():
  40.             self.start_new_path(new_point)
  41.         self.time += dt
  42.         t = self.time * self.glow_speed  # 控制脉冲速度
  43.         intensity = 0.25 * np.sin(t) + 0.75  # 0.5-1之间波动
  44.         # 动态调整透明度
  45.         self.set_stroke(
  46.             opacity=intensity,  # 透明度波动
  47.         )
  48.         self.add_line_to(new_point)
  49.         # 轨迹消散
  50.         if self.dissipating_time:
  51.             if self.time - 1 > self.dissipating_time:
  52.                 nppcc = self.n_points_per_curve
  53.                 self.set_points(self.points[nppcc:])
复制代码
初始化函数(__init__)的参数,代码中已经有详细的注释,不再赘述。
至于更新轨迹的update_path方法,它的关键逻辑有:

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

接下来我们通过几个示例来看看如何使用这个特效。
2.1. 渐变色轨迹

基于上面我们实现的GlowingTracedPath类,实现一个渐变色的轨迹非常简单。
  1. a = Dot(RIGHT * 2)
  2. b = GlowingTracedPath(
  3.     a.get_center,
  4.     gradient_colors=[BLUE, RED, YELLOW],
  5. )
  6. self.add(a, b)
  7. self.play(a.animate(path_arc=PI / 2).shift(LEFT * 2), run_time=2)
  8. self.play(a.animate(path_arc=-PI / 2).shift(LEFT * 2), run_time=2)
复制代码
代码中,轨迹b追踪点a的位置,形成一个由参数gradient_colors指定的渐变色轨迹。
1.gif

2.2. 轨迹逐渐消失

上面的示例中,轨迹不会消失,通过参数dissipating_time,可以指定轨迹存在的时间(单位:秒)。
  1. b = GlowingTracedPath(
  2.     a.get_center,
  3.     gradient_colors=[BLUE, RED, YELLOW],
  4.     dissipating_time=0.5,
  5. )
复制代码
轨迹b的dissipating_time设置为0.5,也就是新产生的轨迹会在0.5秒后逐渐消失。
2.gif

2.3. 轨迹闪烁

最后,来看看轨迹的闪光效果,下面的通过设置两种不同的glow_speed(闪烁的速度),
来比较不同速度下的闪烁效果。
  1. a1 = Dot()
  2. a2 = Dot()
  3. b1 = GlowingTracedPath(
  4.     a1.get_center,
  5.     gradient_colors=[BLUE, RED, YELLOW],
  6.     glow_speed=8,
  7. )
  8. b2 = GlowingTracedPath(
  9.     a2.get_center,
  10.     gradient_colors=[BLUE, RED, YELLOW],
  11.     glow_speed=16,
  12. )
  13. self.add(a1, b1, a2, b2)
  14. heart1 = ImplicitFunction(
  15.     lambda x, y: (x**2 + y**2 - 1) ** 3 - x**2 * y**3,
  16.     color=PINK,
  17.     x_range=[-1.5, 1.5],
  18.     y_range=[-1.2, 1.8],
  19. ).shift(LEFT * 1.5)
  20. heart2 = ImplicitFunction(
  21.     lambda x, y: (x**2 + y**2 - 1) ** 3 - x**2 * y**3,
  22.     color=PINK,
  23.     x_range=[-1.5, 1.5],
  24.     y_range=[-1.2, 1.8],
  25. ).shift(RIGHT * 1.5)
  26. self.play(MoveAlongPath(a1, heart1), MoveAlongPath(a2, heart2), run_time=4)
复制代码
3.gif

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

通过GlowingTracedPath类,我们可以轻松地在Manim中实现带有闪光效果的轨迹。
这个类通过动态调整透明度和颜色渐变,结合轨迹的实时更新,创造出了引人注目的视觉效果。
无论是用于数学动画还是其他创意项目,这种特效都能为你的作品增添独特的魅力。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册