def introduce_bubble(self, *args, **kwargs): if isinstance(args[0], PiCreature): pi_creature = args[0] content = args[1:] else: pi_creature = self.get_primary_pi_creature() content = args bubble_class = kwargs.pop("bubble_class", SpeechBubble) target_mode = kwargs.pop( "target_mode", "thinking" if bubble_class is ThoughtBubble else "speaking" ) bubble_kwargs = kwargs.pop("bubble_kwargs", {}) bubble_removal_kwargs = kwargs.pop("bubble_removal_kwargs", {}) added_anims = kwargs.pop("added_anims", []) anims = [] on_screen_mobjects = self.camera.extract_mobject_family_members( self.get_mobjects() ) def has_bubble(pi): return hasattr(pi, "bubble") and \ pi.bubble is not None and \ pi.bubble in on_screen_mobjects pi_creatures_with_bubbles = list(filter(has_bubble, self.get_pi_creatures())) if pi_creature in pi_creatures_with_bubbles: pi_creatures_with_bubbles.remove(pi_creature) old_bubble = pi_creature.bubble bubble = pi_creature.get_bubble( *content, bubble_class=bubble_class, **bubble_kwargs ) anims += [ ReplacementTransform(old_bubble, bubble), ReplacementTransform(old_bubble.content, bubble.content), pi_creature.change_mode, target_mode ] else: anims.append(PiCreatureBubbleIntroduction( pi_creature, *content, bubble_class=bubble_class, bubble_kwargs=bubble_kwargs, target_mode=target_mode, **kwargs )) anims += [ RemovePiCreatureBubble(pi, **bubble_removal_kwargs) for pi in pi_creatures_with_bubbles ] anims += added_anims self.play(*anims, **kwargs)
def construct(self): number_line = NumberLine(x_min=-2, x_max=2) text_1 = TextMobject("Theorem of") \ .next_to(number_line, DOWN) text_2 = TextMobject("Beethoven") \ .next_to(number_line, DOWN) dashed_line = DashedLine( number_line.get_left(), number_line.get_right(), color=YELLOW, ).set_stroke(width=11) self.add(number_line, text_1) self.play( LaggedStart(*[ ShowCreationThenDestruction(dashed_segment) for dashed_segment in dashed_line ], run_time=5), AnimationGroup(Animation(Mobject(), run_time=2.1), ReplacementTransform(text_1, text_2), lag_ratio=1)) self.wait()
def teacher_holds_up(self, mobject, target_mode="raise_right_hand", added_anims=None, **kwargs): mobject.move_to(self.hold_up_spot, DOWN) mobject.shift_onto_screen() mobject_copy = mobject.copy() mobject_copy.shift(DOWN) mobject_copy.fade(1) added_anims = added_anims or [] self.play( ReplacementTransform(mobject_copy, mobject), self.teacher.change, target_mode, *added_anims )
def play_farey_sum_animation(self, p1, q1, p2, q2): c1, c2, c3, l1, l2, l3 = self.get_farey_sum_key_mobjects(p1, q1, p2, q2) l3.set_color(PINK) self.wait() self.play( ShowCreation(c1), ApplyMethod(l1.set_color, YELLOW), ShowCreation(c2), ApplyMethod(l2.set_color, YELLOW), ) self.play( ReplacementTransform(l1.numer.deepcopy(), l3.numer), ReplacementTransform(l1.line.deepcopy(), l3.line), ReplacementTransform(l1.denom.deepcopy(), l3.denom), ReplacementTransform(l2.numer.deepcopy(), l3.numer), ReplacementTransform(l2.line.deepcopy(), l3.line), ReplacementTransform(l2.denom.deepcopy(), l3.denom), ReplacementTransform(c1.deepcopy(), c3), ReplacementTransform(c2.deepcopy(), c3), ) self.wait() self.play(FadeOut(VGroup(c1, c2, c3, l1, l2, l3)))
def construct_infinite_sum(self): for n in range(1, 11): # Get highlighted terms highlighted_terms = self.get_highlighted_terms(n) # Update highlight rectangles if n == 1: rects = self.get_highlight_rectangles(1) self.play(ShowCreation(rects), lag_ratio=0.2) self.wait() else: new_rects = self.get_highlight_rectangles(n) self.play(Transform(rects, new_rects)) if n <= 4: self.wait() # Show the detailed construction of the first four terms if n <= 4: # Make copies of the elements that are going to be moved highlighted_terms_copy = self.get_highlighted_terms( n).deepcopy() times_symbols_copy = self.get_times_symbols().deepcopy() cdots_copy = self.get_cdots_symbol().deepcopy() # Move highlighted terms into position arranged_terms_list = [] for i in range(4): arranged_terms_list.append(highlighted_terms_copy[i]) arranged_terms_list.append(times_symbols_copy[i]) arranged_terms_list.append(cdots_copy) arranged_terms = VGroup(*arranged_terms_list) arranged_terms.arrange_submobjects(RIGHT, buff=0.2) arranged_terms.next_to(self.sum_tex, UP, aligned_edge=RIGHT, buff=0.5) # Move highlighted terms into position anims_list = [] for i in range(4): anims_list.append( ReplacementTransform( self.get_highlighted_terms(n)[i].deepcopy(), arranged_terms[2 * i], lag_ratio=0, run_time=2)) anims_list.append( ReplacementTransform( self.get_times_symbols()[i].deepcopy(), arranged_terms[2 * i + 1], lag_ratio=0, run_time=2)) anims_list.append( ReplacementTransform(self.get_cdots_symbol().deepcopy(), arranged_terms[-1], lag_ratio=0, run_time=2)) self.play(AnimationGroup(*anims_list)) self.wait() if n == 1: self.play(Transform(arranged_terms, self.get_sum_term(n))) else: self.play( Transform(arranged_terms, self.get_sum_term(n)), Write(self.get_plus_symbol(n - 1)), ) self.wait() # And show the result for the remaining terms else: self.play( Transform( VGroup( self.get_highlighted_terms(n).deepcopy(), self.get_times_symbols().deepcopy(), self.get_cdots_symbol().deepcopy(), ), self.get_sum_term(n), lag_ratio=0, ), Write(self.get_plus_symbol(n - 1)), ) # Add \cdots to the end. self.wait() self.play(FadeOut(rects), Write(self.sum_tex[-1][-4:])) self.wait()
def __init__(self, source: StringMobject, target: StringMobject, **kwargs): digest_config(self, kwargs) assert isinstance(source, StringMobject) assert isinstance(target, StringMobject) anims = [] source_indices = list(range(len(source.labels))) target_indices = list(range(len(target.labels))) def get_filtered_indices_lists(indices_lists, rest_indices): result = [] for indices_list in indices_lists: if not indices_list: continue if not all(index in rest_indices for index in indices_list): continue result.append(indices_list) for index in indices_list: rest_indices.remove(index) return result def add_anims(anim_class, indices_lists_pairs): for source_indices_lists, target_indices_lists in indices_lists_pairs: source_indices_lists = get_filtered_indices_lists( source_indices_lists, source_indices) target_indices_lists = get_filtered_indices_lists( target_indices_lists, target_indices) if not source_indices_lists or not target_indices_lists: continue anims.append( anim_class( source.build_parts_from_indices_lists( source_indices_lists), target.build_parts_from_indices_lists( target_indices_lists), **kwargs)) def get_substr_to_indices_lists_map(part_items): result = {} for substr, indices_list in part_items: if substr not in result: result[substr] = [] result[substr].append(indices_list) return result def add_anims_from(anim_class, func): source_substr_map = get_substr_to_indices_lists_map(func(source)) target_substr_map = get_substr_to_indices_lists_map(func(target)) common_substrings = sorted( [s for s in source_substr_map if s and s in target_substr_map], key=len, reverse=True) add_anims(anim_class, [(source_substr_map[substr], target_substr_map[substr]) for substr in common_substrings]) add_anims(ReplacementTransform, [(source.get_submob_indices_lists_by_selector(k), target.get_submob_indices_lists_by_selector(v)) for k, v in self.key_map.items()]) add_anims_from(FadeTransformPieces, StringMobject.get_specified_part_items) add_anims_from(FadeTransformPieces, StringMobject.get_group_part_items) rest_source = VGroup(*[source[index] for index in source_indices]) rest_target = VGroup(*[target[index] for index in target_indices]) if self.transform_mismatches: anims.append( ReplacementTransform(rest_source, rest_target, **kwargs)) else: anims.append( FadeOutToPoint(rest_source, target.get_center(), **kwargs)) anims.append( FadeInFromPoint(rest_target, source.get_center(), **kwargs)) super().__init__(*anims)
def construct(self): if 1 == 1: try: self.add_sound( "sidewayoutput\\basicmanim\\transform001a_01_01_01_01_01.wav", time_offset=18) self.add_sound( "sidewayoutput\\basicmanim\\transform001a_01_01_01_02_01.wav", time_offset=93) self.add_sound( "sidewayoutput\\basicmanim\\transform001a_01_01_01_03_01.wav", time_offset=135) except: pass self.play( StartScreens01( [], [], [[r"\textbf{\textit{Basic-Manim from }\{Sideway\}}"], [r"\textbf{\textit{Transform}}\\{{Part\ \textspA{I}a}"], [ r"\tiny{\textrm{basic-manim.210200551v0\_transform001a}}" ], [], [ r"\scriptsize{\textbf{Warning:\ The\ content\ may\ contain\ errors,\ mistakes\ and\ inaccuracies.\ Information\ must\ be\ verified\ and\ evaluated\ before\ use.}}" ]], )) if 1 == 1: self.play( GrowFromCenter( TextMobject( r"\textit{\textbf{\underline{Transform}}}").shift( [0, 3.6, 0]))) squarea = Square() squareb = Square(side_length=4).shift([4, 0, 0]) circlea = Circle() circleb = Circle(radius=2).shift([-4, 0, 0]) linea = Line([-4, 3, 0], [4, 3, 0]) lineb = Line([-3, -3, 0], [3, -3, 0]) texta = TextMobject("AB").shift([0, -2.5, 0]) textb = TextMobject("HI").shift([0, 2.5, 0]) self.play( ShowCreation(Group(squarea, circlea, squareb, circleb, linea, lineb), lag_ratio=1, run_time=12)) self.play(Write(VGroup(texta, textb), lag_ratio=1, run_time=10)) self.play(Transform(circlea, squarea, run_time=5)) self.play(Transform(circlea, squareb, path_arc=3, run_time=5)) self.play(Transform(squarea, circleb, path_arc=3, run_time=5)) self.play(Transform(linea, lineb, path_arc=3, run_time=5)) self.play(Transform(linea, circleb, path_arc=3, run_time=5)) self.play(Transform(squareb, lineb, path_arc=3, run_time=5)) self.play(Transform(texta, textb, path_arc=3, run_time=5)) self.play(Transform(texta, circleb, path_arc=3, run_time=5)) self.play(Transform(squareb, textb, path_arc=3, run_time=5)) self.fadeout() if 1 == 1: self.play( GrowFromCenter( TextMobject( r"\textit{\textbf{\underline{Paths\ of\ Transform}}}"). shift([0, 3.6, 0]))) rows, cols = (7, 5) x0, y0 = axes_point([0, 2, cols - 1, -4], [2.3, -1, rows - 1, 3]) txtx = ["loc 1", "loc 2", "m1", "m2"] txty = [ "ClockwiseTransform", "Transform", "CounterclockwiseTransform" ] a1 = Group() a2 = Group() a3 = Group() a4 = Group() for j in range(1, rows): a1.add(Circle().scale(0.2).move_to([x0[1], y0[j], 0])) a2.add(Square().scale(0.2).move_to([x0[2], y0[j], 0])) a3.add( Dot([x0[3], y0[j], 0]).add_updater(lambda mob, obj=a1[ j - 1], x=x0[3], y=y0[j]: mob.become(obj.copy( ).move_to([x, y, 0]))).suspend_updating()) a4.add( Dot([x0[4], y0[j], 0]).add_updater(lambda mob, obj=a2[ j - 1], x=x0[4], y=y0[j]: mob.become(obj.copy( ).move_to([x, y, 0]))).suspend_updating()) self.play(FadeIn( Group( *[ TextMobject(txtx[i]).move_to(each) for i, each in enumerate(coord_grid(x0[1:], y0[0:1])) ], *[ TextMobject(txty[i]).move_to(each) for i, each in enumerate(coord_grid(x0[0:1], y0[1::2])) ], *[Dot(each) for each in coord_grid(x0[1:3], y0[1:])], TextMobject(r"$\rightarrow$").move_to( ([(x0[1] + x0[2]) / 2, y0[0], 0])), a1[::2], a2[::2], a3, a4, *[ Square(stroke_width=2, color="#FFFF00", fill_opacity=0.3).add_updater( lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.2)) for obj in a1 ], *[ Square(stroke_width=2, color="#DC75CD").add_updater( lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.3)) for obj in a2 ])), run_time=5) self.wait(2) self.play(AnimationGroup( ClockwiseTransform(a2[0], a1[0]), ClockwiseTransform(a1[1], a2[1]), Transform(a1[2], a2[2]), Transform(a2[3], a1[3]), CounterclockwiseTransform(a1[4], a2[4]), CounterclockwiseTransform(a2[5], a1[5]), ), run_time=25) self.wait(3) a1.shift([0.3, 0, 0]).set_color("#11FF00") self.wait(3) self.play(ApplyMethod(a1.shift, ([0.3, 0, 0])), run_time=3) self.fadeout() if 1 == 1: self.play( GrowFromCenter( TextMobject( r"\textit{\textbf{\underline{Methods\ of\ Transform}}}" ).shift([0, 3.6, 0]))) rows, cols = (9, 5) x0, y0 = axes_point([0, 2, cols - 1, -4], [2.3, -0.8, rows - 1, 3]) txtx = ["loc 1", "loc 2", "m1", "m2"] txty = [ "Transform", "ReplacementTransform", "TransformFromCopy", "MoveToTarget" ] a1 = Group() a2 = Group() a3 = Group() a4 = Group() for j in range(1, rows): a1.add(Circle().scale(0.2).move_to([x0[1], y0[j], 0])) a2.add(Square().scale(0.2).move_to([x0[2], y0[j], 0])) a3.add(Dot().move_to([x0[3], y0[j], 0]).add_updater( lambda mob, obj=a1[j - 1], x=x0[3], y=y0[j]: mob.become( obj.copy().move_to([x, y, 0]))).suspend_updating()) a4.add(Dot().move_to([x0[4], y0[j], 0]).add_updater( lambda mob, obj=a2[j - 1], x=x0[4], y=y0[j]: mob.become( obj.copy().move_to([x, y, 0]))).suspend_updating()) a1[6].target = a2[6] a1[7].target = a2[7] self.play(FadeIn( Group( *[ TextMobject(txtx[i]).move_to(each) for i, each in enumerate(coord_grid(x0[1:], y0[0:1])) ], *[ TextMobject(txty[i]).move_to(each) for i, each in enumerate(coord_grid(x0[0:1], y0[1::2])) ], *[Dot(each) for each in coord_grid(x0[1:3], y0[1:])], TextMobject(r"$\rightarrow$").move_to( ([(x0[1] + x0[2]) / 2, y0[0], 0])), a1[::2], a2[::2], a3, a4, Group(*[ Square( stroke_width=2, color="#FFFF00", fill_opacity=0.3). add_updater(lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.2)) for obj in a1 ]), Group(*[ Square(stroke_width=2, color="#DC75CD").add_updater( lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.3)) for obj in a2 ]))), run_time=5) self.wait(2) self.play(AnimationGroup(Transform(a1[0], a2[0]), Transform(a1[1], a2[1]), ReplacementTransform(a1[2], a2[2]), ReplacementTransform(a1[3], a2[3]), TransformFromCopy(a1[4], a2[4]), TransformFromCopy(a1[5], a2[5]), MoveToTarget(a1[6]), MoveToTarget(a1[7])), run_time=40) self.wait(3) a1.shift([0.3, 0, 0]).set_color("#11FF00") self.wait(10) self.play(ApplyMethod(a1.shift, ([0.3, 0, 0])), run_time=5) self.fadeout() if 1 == 1: self.play(EndScreen01()) self.wait(5)
def __init__(self, source: LabelledString, target: LabelledString, **kwargs): digest_config(self, kwargs) assert isinstance(source, LabelledString) assert isinstance(target, LabelledString) anims = [] source_indices = list(range(len(source.labelled_submobjects))) target_indices = list(range(len(target.labelled_submobjects))) def get_indices_lists(mobject, parts): return [[ mobject.labelled_submobjects.index(submob) for submob in part ] for part in parts] def add_anims_from(anim_class, func, source_args, target_args=None): if target_args is None: target_args = source_args.copy() for source_arg, target_arg in zip(source_args, target_args): source_parts = func(source, source_arg) target_parts = func(target, target_arg) source_indices_lists = list( filter( lambda indices_list: all([ index in source_indices for index in indices_list ]), get_indices_lists(source, source_parts))) target_indices_lists = list( filter( lambda indices_list: all([ index in target_indices for index in indices_list ]), get_indices_lists(target, target_parts))) if not source_indices_lists or not target_indices_lists: continue anims.append(anim_class(source_parts, target_parts, **kwargs)) for index in it.chain(*source_indices_lists): source_indices.remove(index) for index in it.chain(*target_indices_lists): target_indices.remove(index) def get_common_substrs(substrs_from_source, substrs_from_target): return sorted([ substr for substr in substrs_from_source if substr and substr in substrs_from_target ], key=len, reverse=True) def get_parts_from_keys(mobject, keys): if isinstance(keys, str): keys = [keys] result = VGroup() for key in keys: if not isinstance(key, str): raise TypeError(key) result.add(*mobject.get_parts_by_string(key)) return result add_anims_from(ReplacementTransform, get_parts_from_keys, self.key_map.keys(), self.key_map.values()) add_anims_from( FadeTransformPieces, LabelledString.get_parts_by_string, get_common_substrs(source.specified_substrs, target.specified_substrs)) add_anims_from( FadeTransformPieces, LabelledString.get_parts_by_group_substr, get_common_substrs(source.group_substrs, target.group_substrs)) rest_source = VGroup(*[source[index] for index in source_indices]) rest_target = VGroup(*[target[index] for index in target_indices]) if self.transform_mismatches: anims.append( ReplacementTransform(rest_source, rest_target, **kwargs)) else: anims.append( FadeOutToPoint(rest_source, target.get_center(), **kwargs)) anims.append( FadeInFromPoint(rest_target, source.get_center(), **kwargs)) super().__init__(*anims)