mscene.extrasΒΆ
from manim import *
class DashFlow(DashedVMobject):
"""A dashed VMobject with its dash offset continuously shifting for a flowing effect.
Args:
vmob (VMobject): The VMobject to animate.
rate (float): The rate of shifting dash offset over time (default: 1.0).
**kwargs: Additional keyword arguments passed to DashedVMobject.
Methods:
play():
Resume updater to play animation.
pause():
Suspend updater to pause animation.
stop():
Clear updater to stop animation.
"""
def __init__(self, vmob, rate=1.0, dash_offset=0, **kwargs):
vmob = vmob.copy()
super().__init__(vmob, dash_offset=dash_offset, **kwargs)
self.rate = rate
self.offset = dash_offset
def _updater(mobj, dt):
self.offset = (self.offset + dt * self.rate) % 1
mobj.become(DashedVMobject(vmob, dash_offset=self.offset, **kwargs))
self.add_updater(_updater)
def play(self):
self.resume_updating()
def pause(self):
self.suspend_updating()
def stop(self):
self.clear_updaters()
class DrawArc(Succession):
def __init__(self, arc, reverse=False, run_time=2, **kwargs):
quarter_time = run_time / 4
half_time = run_time / 2
if reverse:
line = Line(
arc.get_arc_center(),
arc.get_end(),
stroke_width=arc.get_stroke_width(),
stroke_color=arc.get_stroke_color(),
)
create_arc = Uncreate(arc, run_time=half_time)
rotate_line = Rotate(
line, -arc.angle, about_point=arc.get_arc_center(), run_time=half_time
)
else:
line = Line(
arc.get_arc_center(),
arc.get_start(),
stroke_width=arc.get_stroke_width(),
stroke_color=arc.get_stroke_color(),
)
create_arc = Create(arc, run_time=half_time)
rotate_line = Rotate(
line, arc.angle, about_point=arc.get_arc_center(), run_time=half_time
)
super().__init__(
Create(line, run_time=quarter_time),
AnimationGroup(
create_arc,
rotate_line,
),
Uncreate(line, run_time=quarter_time),
**kwargs,
)
class FlashFade(AnimationGroup):
"""Animation for fading VMobjects with flashing outlines.
Args:
vmob (VMobject): The VMobject to animate.
mode (str): "IN" to fade in, "OUT" to fade out, "AUTO" to fade in and out (default: "AUTO").
reverse (bool): If True, reverses the animation direction (default: False).
color (ManimColor | None): The stroke color of the flash outline (default: None).
width (float | None): The stroke width of the flash outline (default: None).
opacity (float | None): The stroke opacity of the flash outline (default: None).
time_width (float): The length of the sliver relative to the length of the stroke (default: 0.5).
duration (float): The duration of each sub-animation (default: 1.0).
lag_ratio (float): The lag ratio between sub-animations (default: 0.125).
**kwargs: Additional keyword arguments for AnimationGroup.
"""
def __init__(
self,
vmob: VMobject,
mode="AUTO",
reverse=False,
color=None,
width=None,
opacity=None,
time_width=0.5,
duration=1.0,
lag_ratio=0.125,
**kwargs,
):
if reverse:
vmob = vmob[::-1]
vcopy = vmob.copy()
vcopy.set_fill(opacity=0).set_stroke(color, width, opacity)
for vm in vcopy:
vm = vm.reverse_direction()
else:
vcopy = vmob.copy()
vcopy.set_fill(opacity=0).set_stroke(color, width, opacity)
mode = mode.upper()
n = len(vmob)
anim = []
if mode == "IN":
for i in range(n):
anim.append(
AnimationGroup(
FadeIn(vmob[i]),
ShowPassingFlash(vcopy[i], time_width=time_width),
run_time=duration,
)
)
elif mode == "OUT":
for i in range(n):
anim.append(
AnimationGroup(
FadeOut(vmob[i]),
ShowPassingFlash(vcopy[i], time_width=time_width),
run_time=duration,
)
)
else:
for i in range(n):
anim.append(
AnimationGroup(
FadeIn(vmob[i].copy(), rate_func=there_and_back_with_pause),
ShowPassingFlash(vcopy[i], time_width=time_width),
run_time=duration,
)
)
super().__init__(*anim, lag_ratio=lag_ratio, **kwargs)