mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Updates to (some) indication animations
This commit is contained in:
parent
69cf682f07
commit
14b9db61b9
1 changed files with 83 additions and 53 deletions
|
@ -9,10 +9,13 @@ from manimlib.animation.composition import AnimationGroup
|
|||
from manimlib.animation.composition import Succession
|
||||
from manimlib.animation.creation import ShowCreation
|
||||
from manimlib.animation.creation import ShowPartial
|
||||
from manimlib.animation.fading import FadeIn
|
||||
from manimlib.animation.fading import FadeOut
|
||||
from manimlib.animation.transform import Transform
|
||||
from manimlib.animation.update import UpdateFromAlphaFunc
|
||||
from manimlib.mobject.updater import updating_mobject_from_func
|
||||
from manimlib.mobject.mobject import Mobject
|
||||
from manimlib.mobject.types.vectorized_mobject import VMobject
|
||||
from manimlib.mobject.geometry import Circle
|
||||
from manimlib.mobject.geometry import Dot
|
||||
from manimlib.mobject.shape_matchers import SurroundingRectangle
|
||||
|
@ -35,19 +38,27 @@ class FocusOn(Transform):
|
|||
"remover": True,
|
||||
}
|
||||
|
||||
def __init__(self, mobject_or_point, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
big_dot = Dot(
|
||||
def __init__(self, focus_point, **kwargs):
|
||||
self.focus_point = focus_point
|
||||
# Initialize with blank mobject, while create_target
|
||||
# and create_starting_mobject handle the meat
|
||||
super().__init__(VMobject(), **kwargs)
|
||||
|
||||
def create_target(self):
|
||||
little_dot = Dot(radius=0)
|
||||
little_dot.set_fill(self.color, opacity=self.opacity)
|
||||
little_dot.add_updater(
|
||||
lambda d: d.move_to(self.focus_point)
|
||||
)
|
||||
return little_dot
|
||||
|
||||
def create_starting_mobject(self):
|
||||
return Dot(
|
||||
radius=FRAME_X_RADIUS + FRAME_Y_RADIUS,
|
||||
stroke_width=0,
|
||||
fill_color=self.color,
|
||||
fill_opacity=0,
|
||||
)
|
||||
little_dot = Dot(radius=0)
|
||||
little_dot.set_fill(self.color, opacity=self.opacity)
|
||||
little_dot.move_to(mobject_or_point)
|
||||
|
||||
Transform.__init__(self, big_dot, little_dot, **kwargs)
|
||||
|
||||
|
||||
class Indicate(Transform):
|
||||
|
@ -57,12 +68,11 @@ class Indicate(Transform):
|
|||
"color": YELLOW,
|
||||
}
|
||||
|
||||
def __init__(self, mobject, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
target = mobject.copy()
|
||||
def create_target(self):
|
||||
target = self.mobject.copy()
|
||||
target.scale_in_place(self.scale_factor)
|
||||
target.set_color(self.color)
|
||||
Transform.__init__(self, mobject, target, **kwargs)
|
||||
return target
|
||||
|
||||
|
||||
class Flash(AnimationGroup):
|
||||
|
@ -71,51 +81,62 @@ class Flash(AnimationGroup):
|
|||
"num_lines": 12,
|
||||
"flash_radius": 0.3,
|
||||
"line_stroke_width": 3,
|
||||
"run_time": 1,
|
||||
}
|
||||
|
||||
def __init__(self, point, color=YELLOW, **kwargs):
|
||||
self.point = point
|
||||
self.color = color
|
||||
digest_config(self, kwargs)
|
||||
self.lines = self.create_lines()
|
||||
animations = self.create_line_anims()
|
||||
super().__init__(
|
||||
*animations,
|
||||
group=self.lines,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def create_lines(self):
|
||||
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_color(self.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
|
||||
]
|
||||
lines.add_updater(lambda l: l.move_to(self.point))
|
||||
return lines
|
||||
|
||||
AnimationGroup.__init__(
|
||||
self, *line_anims + fade_anims, **kwargs
|
||||
)
|
||||
def create_line_anims(self):
|
||||
return [
|
||||
ShowCreationThenDestruction(line)
|
||||
for line in self.lines
|
||||
]
|
||||
|
||||
|
||||
class CircleIndicate(Indicate):
|
||||
CONFIG = {
|
||||
"rate_func": squish_rate_func(there_and_back, 0, 0.8),
|
||||
"remover": True
|
||||
"rate_func": there_and_back,
|
||||
"remover": True,
|
||||
"circle_config": {
|
||||
"color": YELLOW,
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(self, mobject, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
circle = Circle(color=self.color, **kwargs)
|
||||
circle.surround(mobject)
|
||||
Indicate.__init__(self, circle, **kwargs)
|
||||
circle = self.get_circle(mobject)
|
||||
super().__init__(circle, **kwargs)
|
||||
|
||||
def get_circle(self, mobject):
|
||||
circle = Circle(**self.circle_config)
|
||||
circle.add_updater(lambda c: c.surround(mobject))
|
||||
return circle
|
||||
|
||||
def interpolate_mobject(self, alpha):
|
||||
super().interpolate_mobject(alpha)
|
||||
self.mobject.set_stroke(opacity=alpha)
|
||||
|
||||
|
||||
class ShowPassingFlash(ShowPartial):
|
||||
|
@ -132,10 +153,10 @@ class ShowPassingFlash(ShowPartial):
|
|||
lower = max(lower, 0)
|
||||
return (lower, upper)
|
||||
|
||||
def clean_up_from_scene(self, *args, **kwargs):
|
||||
ShowPartial.clean_up_from_scene(self, *args, **kwargs)
|
||||
for submob, start_submob in self.get_all_families_zipped():
|
||||
submob.pointwise_become_partial(start_submob, 0, 1)
|
||||
def finish(self):
|
||||
super().finish()
|
||||
for submob, start in self.get_all_families_zipped():
|
||||
submob.pointwise_become_partial(start, 0, 1)
|
||||
|
||||
|
||||
class ShowCreationThenDestruction(ShowPassingFlash):
|
||||
|
@ -151,10 +172,9 @@ class ShowCreationThenFadeOut(Succession):
|
|||
}
|
||||
|
||||
def __init__(self, mobject, **kwargs):
|
||||
Succession.__init__(
|
||||
self,
|
||||
ShowCreation, mobject,
|
||||
FadeOut, mobject,
|
||||
super().__init__(
|
||||
ShowCreation(mobject),
|
||||
FadeOut(mobject),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
@ -165,34 +185,44 @@ class AnimationOnSurroundingRectangle(AnimationGroup):
|
|||
# Function which takes in a rectangle, and spits
|
||||
# out some animation. Could be some animation class,
|
||||
# could be something more
|
||||
"rect_to_animation": Animation
|
||||
"rect_animation": Animation
|
||||
}
|
||||
|
||||
def __init__(self, mobject, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
rect = SurroundingRectangle(
|
||||
mobject, **self.surrounding_rectangle_config
|
||||
)
|
||||
if "surrounding_rectangle_config" in kwargs:
|
||||
kwargs.pop("surrounding_rectangle_config")
|
||||
AnimationGroup.__init__(self, self.rect_to_animation(rect, **kwargs))
|
||||
self.mobject_to_surround = mobject
|
||||
|
||||
rect = self.get_rect()
|
||||
rect.add_updater(lambda r: r.move_to(mobject))
|
||||
|
||||
super().__init__(
|
||||
self.rect_animation(rect, **kwargs),
|
||||
)
|
||||
|
||||
def get_rect(self):
|
||||
return SurroundingRectangle(
|
||||
self.mobject_to_surround,
|
||||
**self.surrounding_rectangle_config
|
||||
)
|
||||
|
||||
|
||||
class ShowPassingFlashAround(AnimationOnSurroundingRectangle):
|
||||
CONFIG = {
|
||||
"rect_to_animation": ShowPassingFlash
|
||||
"rect_animation": ShowPassingFlash
|
||||
}
|
||||
|
||||
|
||||
class ShowCreationThenDestructionAround(AnimationOnSurroundingRectangle):
|
||||
CONFIG = {
|
||||
"rect_to_animation": ShowCreationThenDestruction
|
||||
"rect_animation": ShowCreationThenDestruction
|
||||
}
|
||||
|
||||
|
||||
class ShowCreationThenFadeAround(AnimationOnSurroundingRectangle):
|
||||
CONFIG = {
|
||||
"rect_to_animation": ShowCreationThenFadeOut
|
||||
"rect_animation": ShowCreationThenFadeOut
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue