def __init__(self, point, color=YELLOW, **kwargs): digest_config(self, kwargs) lines = VGroup() for angle in np.arange(0, TAU, TAU / self.num_lines): line = Line(ORIGIN, self.line_length * RIGHT) line.shift((self.flash_radius - self.line_length) * RIGHT) line.rotate(angle, about_point=ORIGIN) lines.add(line) lines.move_to(point) lines.set_color(color) lines.set_stroke(width=3) line_anims = [ ShowCreationThenDestruction( line, rate_func=squish_rate_func(smooth, 0, 0.5) ) for line in lines ] fade_anims = [ UpdateFromAlphaFunc( line, lambda m, a: m.set_stroke( width=self.line_stroke_width * (1 - a) ), rate_func=squish_rate_func(smooth, 0, 0.75) ) for line in lines ] AnimationGroup.__init__( self, *line_anims + fade_anims, **kwargs )
class Blink(ApplyMethod): CONFIG = { "rate_func": squish_rate_func(there_and_back) } def __init__(self, pi_creature, **kwargs): ApplyMethod.__init__(self, pi_creature.blink, **kwargs)
def __init__(self, AnimationClass, mobject, arg_creator=None, **kwargs): for key in ["rate_func", "run_time"]: if key in AnimationClass.CONFIG: setattr(self, key, AnimationClass.CONFIG[key]) digest_config(self, kwargs) for key in "rate_func", "run_time", "lag_ratio": if key in kwargs: kwargs.pop(key) if arg_creator is None: def arg_creator(mobject): return (mobject,) self.subanimations = [ AnimationClass( *arg_creator(submob), run_time=self.run_time, rate_func=squish_rate_func( self.rate_func, beta, beta + self.lag_ratio ), **kwargs ) for submob, beta in zip( mobject, np.linspace(0, 1 - self.lag_ratio, len(mobject)) ) ] Animation.__init__(self, mobject, **kwargs)
class TransformAnimations(Transform): CONFIG = {"rate_func": squish_rate_func(smooth)} def __init__(self, start_anim, end_anim, **kwargs): digest_config(self, kwargs, locals()) if "run_time" in kwargs: self.run_time = kwargs.pop("run_time") else: self.run_time = max(start_anim.run_time, end_anim.run_time) for anim in start_anim, end_anim: anim.set_run_time(self.run_time) if start_anim.starting_mobject.get_num_points( ) != end_anim.starting_mobject.get_num_points(): start_anim.starting_mobject.align_data(end_anim.starting_mobject) for anim in start_anim, end_anim: if hasattr(anim, "target_mobject"): anim.starting_mobject.align_data(anim.target_mobject) Transform.__init__(self, start_anim.mobject, end_anim.mobject, **kwargs) # Rewire starting and ending mobjects start_anim.mobject = self.starting_mobject end_anim.mobject = self.target_mobject def interpolate(self, alpha): self.start_anim.interpolate(alpha) self.end_anim.interpolate(alpha) Transform.interpolate(self, alpha)
def begin(self) -> None: # This is called right as an animation is being # played. As much initialization as possible, # especially any mobject copying, should live in # this method if self.time_span is not None: start, end = self.time_span self.run_time = max(end, self.run_time) self.rate_func = squish_rate_func( self.rate_func, start / self.run_time, end / self.run_time, ) self.mobject.set_animating_status(True) self.starting_mobject = self.create_starting_mobject() if self.suspend_mobject_updating: # All calls to self.mobject's internal updaters # during the animation, either from this Animation # or from the surrounding scene, should do nothing. # It is, however, okay and desirable to call # the internal updaters of self.starting_mobject, # or any others among self.get_all_mobjects() self.mobject.suspend_updating() self.families = list(self.get_all_families_zipped()) self.interpolate(0)
class CircleIndicate(Indicate): """ Type: ``Indicate`` Parameters ---------- mobject : Mobject TODO ``CONFIG`` parameters :: "rate_func": squish_rate_func(there_and_back, 0, 0.8), "remover": True """ CONFIG = { "rate_func": squish_rate_func(there_and_back, 0, 0.8), "remover": True } def __init__(self, mobject, **kwargs): digest_config(self, kwargs) circle = Circle(color=self.color, **kwargs) circle.surround(mobject) Indicate.__init__(self, circle, **kwargs)
def get_rate_func(pi): index = creatures_list.index(pi) proportion = float(index) / len(creatures_list) start_time = 0.8 * proportion return squish_rate_func( there_and_back, start_time, start_time + 0.2 )
class CircleIndicate(Indicate): CONFIG = { "rate_func": squish_rate_func(there_and_back, 0, 0.8), "remover": True } def __init__(self, mobject, **kwargs): digest_config(self, kwargs) circle = Circle(color=self.color, **kwargs) circle.surround(mobject) Indicate.__init__(self, circle, **kwargs)
def __init__(self, vmobject: VMobject, stroke_width: float = 2, **kwargs): digest_config(self, kwargs) outline = vmobject.copy() outline.set_fill(opacity=0) outline.set_stroke(width=stroke_width, opacity=1) rate_func = kwargs.get("rate_func", smooth) super().__init__( FadeIn(vmobject, rate_func=squish_rate_func(rate_func, self.fade_lag, 1)), VShowPassingFlash(outline, time_width=1), **kwargs)
def get_logo_animations(self, logo): layers = logo.spike_layers for j, layer in enumerate(layers): for i, spike in enumerate(layer): spike.angle = (13 * (i + 1) * (j + 1) * TAU / 28) % TAU if spike.angle > PI: spike.angle -= TAU spike.save_state() spike.rotate(spike.angle, about_point=ORIGIN) # spike.get_points()[1] = rotate_vector( # spike.get_points()[1], TAU/28, # ) # spike.get_points()[-1] = rotate_vector( # spike.get_points()[-1], -TAU/28, # ) def get_spike_animation(spike, **kwargs): return Restore(spike, path_arc=-spike.angle, **kwargs) logo.iris_background.save_state() # logo.iris_background.scale(0.49) logo.iris_background.set_fill(GREY_D, 0.5) return [ Restore( logo.iris_background, rate_func=squish_rate_func(smooth, 2.0 / 3, 1), run_time=3, ), AnimationGroup(*[ LaggedStartMap( get_spike_animation, layer, run_time=2, # rate_func=squish_rate_func(smooth, a / 3.0, (a + 0.9) / 3.0), lag_ratio=0.2, ) for layer, a in zip(layers, [0, 2, 1, 0]) ]), Animation(logo.pupil), ]
def construct(self): logo = self.logo name = self.channel_name layers = logo.spike_layers logo.save_state() for layer in layers: for spike in layer: spike.save_state() point = np.array(spike.get_points()[0]) angle = angle_of_vector(point) spike.rotate(-angle + 90 * DEGREES) spike.stretch_to_fit_width(0.2) spike.stretch_to_fit_height(0.5) spike.point = point for spike in layer[::2]: spike.rotate(180 * DEGREES) layer.arrange(LEFT, buff=0.1) layers.arrange(UP) layers.to_edge(DOWN) wrong_spike = layers[1][-5] wrong_spike.real_saved_state = wrong_spike.saved_state.copy() wrong_spike.saved_state.scale(0.25, about_point=wrong_spike.point) wrong_spike.saved_state.rotate(90 * DEGREES) self.wrong_spike = wrong_spike def get_spike_animation(spike, **kwargs): return Restore(spike, **kwargs) logo.iris_background.save_state() logo.iris_background.set_fill(opacity=0.0) logo.iris_background.scale(0.8) alt_name = name.copy() alt_name.set_stroke(BLACK, 5) self.play( Restore( logo.iris_background, rate_func=squish_rate_func(smooth, 1.0 / 3, 1), run_time=2, ), AnimationGroup(*( LaggedStartMap( get_spike_animation, layer, run_time=2, # rate_func=squish_rate_func(smooth, a / 3.0, (a + 0.9) / 3.0), lag_ratio=2 / len(layer), path_arc=-90 * DEGREES) for layer, a in zip(layers, [0, 2, 1, 0]))), Animation(logo.pupil), Write(alt_name), Write(name), run_time=3) self.wait(0.25) self.play(Transform( wrong_spike, wrong_spike.real_saved_state, ), Animation(self.logo), run_time=0.75)