def __init__(self, eq1, eq2, regex, regex2=None, map_list=None, align_char=None): # align equations if align_char: difference_vec = \ self.mob_from_char(eq1, eq1.tex_string, align_char).get_center() - \ self.mob_from_char(eq2, eq2.tex_string, align_char).get_center() else: difference_vec = eq1.get_center() - eq2.get_center() eq2.shift(difference_vec) if regex2 is None: g1 = self.split_by_regex(eq1, regex) g2 = self.split_by_regex(eq2, regex) assert (len(g1.submobjects) == len(g2.submobjects)) trans = ReplacementTransform(g1, g2) AnimationGroup.__init__(self, trans) else: assert (map_list) g1 = self.split_by_regex(eq1, regex) g2 = self.split_by_regex(eq2, regex2) self.g1 = g1 self.g2 = g2 G1 = VGroup() G2 = VGroup() F1 = Group() F2 = Group() g1_nodes = set(pair[0] for pair in map_list) g2_nodes = set(pair[1] for pair in map_list) while map_list: l1 = [g1.submobjects[map_list[0][0]]] l2 = [g2.submobjects[map_list[0][1]]] new_list = [] for i in range(1, len(map_list)): if map_list[i][0] == map_list[0][0]: l2.append(g2.submobjects[map_list[i][1]]) elif map_list[i][1] == map_list[0][1]: l1.append(g1.submobjects[map_list[i][0]]) else: new_list.append(map_list[i]) map_list = new_list G1.submobjects.append(VGroup(*l1)) G2.submobjects.append(VGroup(*l2)) for i in range(len(g1.submobjects)): if i not in g1_nodes: F1.submobjects.append(g1.submobjects[i]) for i in range(len(g2.submobjects)): if i not in g2_nodes: F2.submobjects.append(g2.submobjects[i]) self.g1 = g1 self.g2 = g2 trans = ReplacementTransform(G1, G2) fadeout = FadeOut(F1) fadein = FadeIn(F2) AnimationGroup.__init__(self, trans, fadeout, fadein)
def construct(self): self.quote = self.get_quote() self.author = self.get_author(self.quote) self.play(FadeIn(self.quote, **self.fade_in_kwargs)) self.wait(2) self.play(Write(self.author, run_time=3)) self.wait()
def construct(self): author = TextMobject("@Solara570") support = TextMobject("(Powered by @3Blue1Brown)") author.scale(1.8) support.match_width(author) group = VGroup(author, support) group.arrange_submobjects(DOWN) group.to_corner(RIGHT+DOWN) self.play(FadeIn(group)) self.wait(2)
def rhs_could_be_any_number(self): rhs_list = [ "2", # The journey starts here. "3", # The first number that pops into your head when you hear "2". "\\pi", # The good ol' pi. "\\sqrt{2}", # The (most) famous irrational number. "42", # The answer to everything. "17.29", # TAXI.CAB "-1", # A negative number, because why not? "e", # The (most) famous mathematical constant. "\\dfrac{3+\\sqrt{13}}{2}", # The bronze ratio... and a fraction. "570", # 1/3 of the author. "\\varphi", # The golden ratio. "g_{64}", # Gigigigigigigigantic... "0", # And... stop! "N", ] anything_text = TextMobject("等号右边似乎可以放任何数...") anything_text.set_color(YELLOW) anything_text.to_edge(UP) equations = [ VGroup(ExpTower(order = 5), TexMobject("=", rhs).scale(0.8)).scale(2.5) for rhs in rhs_list ] init_equation = equations[0] init_equation.arrange_submobjects(RIGHT, aligned_edge = DOWN) init_equation.next_to(anything_text, DOWN, buff = self.tower_edge_buff) init_equation.to_edge(LEFT, buff = self.tower_edge_buff) for equation in equations: equation[0].move_to(init_equation[0]) equation[1][0].move_to(init_equation[1][0]) equation[1][1].move_to(init_equation[1][1], aligned_edge = LEFT) self.play(FadeIn(init_equation)) self.wait() self.play(Write(anything_text), run_time = 1) self.play( ShowCreationThenDestruction(SurroundingRectangle(init_equation[1][1])), run_time = 2 ) self.wait() for k, equation in enumerate(equations): if k > 0 and k != len(equations)-1: equation[0].move_to(init_equation[0]) equation[1].move_to(init_equation[1], aligned_edge = LEFT) self.remove(equations[k-1]) self.add(equations[k]) self.wait(1./3) elif k == len(equations)-1: self.wait() self.play(ReplacementTransform(equations[k-1], equations[k])) self.wait() self.anything_text = anything_text self.equation = equations[-1]
def solve_the_equations(self): rects = VGroup(*[ CoverRectangle( equation[0].get_exponent(), stroke_color = color, text = str(num), text_color = color ) for equation, color, num in zip(self.equations, self.colors, self.nums) ]) self.play(DrawBorderThenFill(rects)) self.wait() sps = VGroup() for equation, num, color in zip(self.equations, self.nums, self.colors): sp = TexMobject("x", "^{%d}" % num, "=", "%d" % num) sp[1::2].set_color(color) sp.scale(2) sp.next_to(equation, DOWN, buff = 1) sps.add(sp) rss = VGroup() for num, sp, color in zip(self.nums, sps, self.colors): rs = TexMobject("x", "=", "%d" % num , "^{{1}\\over{%d}}" % num, "=\\sqrt{2}") for tex in (rs[2], rs[3][2]): tex.set_color(color) rs.match_height(sp).move_to(sp) rss.add(rs) tf_anims = [] for sp, rs in zip(sps, rss): tf_anims.append(ReplacementTransform(sp[0], rs[0])) tf_anims.append(ReplacementTransform(sp[1], rs[3][2], path_arc = -TAU/4)) tf_anims.append(ReplacementTransform(sp[2], rs[1])) tf_anims.append(ReplacementTransform(sp[3], rs[2])) tf_anims.append(Write(rs[3][:2])) self.play(FadeIn(sps)) self.wait() self.play(AnimationGroup(*tf_anims), run_time = 2) self.wait() self.play(Write(VGroup(*[rs[4:] for rs in rss]), submobject_mode = "all_at_once")) self.wait() self.play(FadeOut(rects)) self.wait() self.rss = rss
def show_comments(self): height = 1.5 simple, but, trap = texts = TextMobject("简单直观", "但是", "暗藏陷阱") texts.scale(1.5) texts.arrange_submobjects(DOWN, buff = 0.8) tick = TickButton() tick.set_height(height) tick.next_to(simple, RIGHT) danger = DangerSign() danger.set_height(height) danger.next_to(trap, LEFT) words = [(simple, tick), (but, ), (danger, trap)] colors = [GREEN, WHITE, RED] for word, color in zip(words, colors): VGroup(word).set_color(color) self.play(FadeIn(VGroup(word)), run_time = 1) self.wait(0.5) self.wait() self.words = words
def update_mobject(self, new_mob, animate=True): """ Returns a list of animations of the mobject being updated """ ret = [] if animate: if type(self.mobject) == Line and type(new_mob) == Arrow: ret.extend([ FadeOut(self.mobject, parent=self), FadeIn(new_mob, parent=self), ]) else: ret.extend( [ReplacementTransform(self.mobject, new_mob, parent=self)]) else: if hasattr(self, "mobject"): self.remove(self.mobject) self.add(new_mob) self.mobject = new_mob return ret
def get_digit_increment_animations(self): result = [] self.number += 1 is_next_digit = self.is_next_digit() if is_next_digit: self.max_place += 1 new_number_mob = self.get_number_mob(self.number) new_number_mob.move_to(self.number_mob, RIGHT) if is_next_digit: self.add_configuration() place = len(new_number_mob.split()) - 1 result.append(FadeIn(self.dot_templates[place])) arrow = Arrow(new_number_mob[place].get_top(), self.dot_templates[place].get_bottom(), color=self.digit_place_colors[place]) self.arrows.add(arrow) result.append(ShowCreation(arrow)) result.append( Transform(self.number_mob, new_number_mob, submobject_mode="lagged_start")) return result
def construct(self): # Setup self.set_camera_orientation(phi = np.pi/3, theta = 3*np.pi/4) self.begin_ambient_camera_rotation(np.pi/50) # Part 1: Increasing the order for order in range(1, self.max_order+1): if order == 1: fractal = HilbertCurve3D(order = 1) self.play(ShowCreation(fractal), run_time = 2) cur_order = fractal.order else: new_fractal = HilbertCurve3D(order = cur_order + 1) self.play(Transform(fractal, new_fractal)) cur_order = new_fractal.order self.wait(2) self.wait(5) self.play(FadeOut(fractal)) self.wait(3) # Part 2: Show one-touch construction self.play(ShowCreation(fractal, run_time = 60)) self.wait(5) # Part 3: Decreasing the order till it vanishes for k in reversed(range(1, self.max_order)): new_fractal = HilbertCurve3D(order = cur_order - 1) self.play(Transform(fractal, new_fractal)) cur_order = new_fractal.order self.wait(2) self.play(Uncreate(fractal), run_time = 1) # The end self.stop_ambient_camera_rotation() self.set_camera_orientation(phi = 0, theta = -np.pi/2) author = TextMobject("@Solara570") author.scale(1.5) author.to_corner(RIGHT+DOWN) self.play(FadeIn(author), run_time = 1) self.wait(2)
def reveal_2_is_4(self): sqrt2_towers = VGroup(*[ ExpTower(element = "\\sqrt{2}", order = 5).match_height(x_tower) \ .move_to(x_tower, aligned_edge = RIGHT) for x_tower in self.x_towers ]) self.play( Transform(self.x_towers, sqrt2_towers, submobject_mode = "lagged_start"), run_time = 2, ) self.wait() self.play(FadeOut(self.rss)) self.wait() two_equals_four = TexMobject("2", "=", "4") for tex, color in zip(two_equals_four, [GREEN, WHITE, RED]): tex.set_color(color) two_equals_four.scale(3) two_equals_four.to_edge(DOWN, buff = 1) sources = VGroup(*[ self.equations[i][j][k].copy() for i, j, k in [(0, 1, 1), (1, 1, 0), (1, 1, 1)] ]) for source, target in zip(sources, two_equals_four): self.play(Transform(source, target)) self.wait() fake_qed = FakeQEDSymbol(order = 2, jagged_percentage = 0.3) fake_qed.next_to(two_equals_four, RIGHT, aligned_edge = DOWN, buff = 1) self.play(FadeIn(fake_qed)) self.wait() issue = TextMobject("思考:\\\\问题在哪?") issue.set_color(YELLOW) issue.to_corner(RIGHT+DOWN) self.play(Write(issue), run_time = 1) self.wait(2)
def construct(self): # Setup axes_group = self.axes_group pos_axis, time_axis = axes_group[:2] title_pq = self.title_pq walk_q = self.walk_q parts_q = self.parts_q l_arrow = self.l_arrow self.add(axes_group, title_pq, walk_q, l_arrow) walk_q_copy = walk_q.copy() # Q_4 -> P_4 steps_qp = VGroup(*[ TextMobject(text) for text in [ "1. 找到路径终点的位置坐标$h$", "2. 找到最晚一次穿过$\\frac{h}{2}$的时刻", "3. 在这个时刻上进行分割", "4. 将第一段水平翻转", "5. 拼接两个片段" ] ]) for step in steps_qp: step.set_color(YELLOW) step.add_background_rectangle() step1_qp, step2_qp, step3_qp, step4_qp, step5_qp = steps_qp # 1. Find the endpoint step1_qp.next_to(time_axis.number_to_point(4.5), UP) end_horiz_line = DashedLine(LEFT_SIDE, RIGHT_SIDE, color=YELLOW) end_horiz_line.move_to(pos_axis.number_to_point(-4)) end_horiz_line.horizontally_center() end_brace_line = DashedLine(time_axis.number_to_point(8), walk_q.get_end_point()) end_brace = Brace(end_brace_line, direction=RIGHT, color=YELLOW) h = TexMobject("h").set_color(YELLOW) end_brace.put_at_tip(h) self.play(Write(step1_qp), ShowCreation(end_horiz_line), run_time=1) self.play(GrowFromCenter(end_brace), GrowFromCenter(h)) self.wait(1.5) self.play(FadeOut(step1_qp)) # 2. Find the last time it GOES THROUGH half its final value half_point = walk_q.get_arrow_end_point(3) step2_qp.next_to(time_axis.number_to_point(4.5), UP) half_horiz_line = end_horiz_line.copy().shift(2 * UP) half_brace_line = DashedLine(time_axis.number_to_point(4), half_point) half_brace = Brace(half_brace_line, direction=RIGHT, color=YELLOW) half_h = TexMobject("\\frac{h}{2}").set_color(YELLOW) half_brace.put_at_tip(half_h) half_dot = Dot(half_point, color=YELLOW) self.play(FadeIn(step2_qp), run_time=1) self.wait(0.5) self.play( ReplacementTransform(end_brace, half_brace), ReplacementTransform(end_horiz_line, half_horiz_line), ReplacementTransform(h, half_h[0]), Write(half_h[1:]), ) self.play(DrawBorderThenFill(half_dot)) self.wait(1.5) self.play( FadeOut(VGroup(step2_qp, half_horiz_line, half_brace, half_h))) # 3. Split vert_line = DashedLine(2.5 * UP, 2.5 * DOWN, color=YELLOW) vert_line.move_to(half_point) step3_qp.next_to(vert_line, UP) left_part_q, right_part_q = parts_q self.play(ShowCreation(vert_line), Write(step3_qp), run_time=1) self.play( FadeOut(half_dot), left_part_q.shift, 0.5 * DOWN + 0.5 * LEFT, right_part_q.shift, 0.5 * UP + 0.5 * RIGHT, ) self.wait(1.5) self.play(FadeOut(vert_line), FadeOut(step3_qp)) # 4. Flip the first segment horizontally flip_axis = DashedLine(2 * UP, 2 * DOWN, color=GREY) flip_axis.move_to(left_part_q) step4_qp.next_to(flip_axis, DOWN) self.play( ShowCreation(flip_axis), Write(step4_qp), run_time=1, ) self.play( left_part_q.flip, Animation(flip_axis), ) self.wait(1.5) self.play(FadeOut(step4_qp), FadeOut(flip_axis)) # 5. Put the pieces together step5_qp.shift(2.5 * DOWN) flip_arrow_anims = walk_q.get_flip_arrows_animation(3, color=ORANGE) self.play(Write(step5_qp), run_time=1) self.wait(0.5) self.play(flip_arrow_anims, right_part_q.set_color, ORANGE) self.wait(0.5) self.play( left_part_q.shift, 2.5 * UP + 0.5 * RIGHT, right_part_q.shift, 3.5 * UP + 0.5 * LEFT, Animation(step5_qp), ) self.wait(0.5) self.play(FadeOut(step5_qp)) self.wait(1.5) # Now Reset self.play(FadeOut(walk_q)) self.play(FadeIn(walk_q_copy)) self.wait()
def construct(self): # Setup axes_group = self.axes_group title_pq = self.title_pq walk_p = self.walk_p parts_p = self.parts_p r_arrow = self.r_arrow self.add(axes_group, title_pq, walk_p, r_arrow) walk_p_copy = walk_p.copy() # P_4 -> Q_4 steps_pq = VGroup(*[ TextMobject(text) for text in [ "1. 第一步是沿着正方向走的", "2. 找到第一次到达最大值的时刻", "3. 在这个时刻上进行分割", "4. 将第一段水平翻转", "5. 拼接两个片段" ] ]) for step in steps_pq: step.set_color(YELLOW) step.add_background_rectangle() step1_pq, step2_pq, step3_pq, step4_pq, step5_pq = steps_pq # 1. Check the first step of the walk step1_circle = Circle(color=YELLOW) first_arrow = walk_p.get_arrow_by_number(0) step1_circle.surround(first_arrow) step1_pq.next_to(step1_circle, RIGHT + DOWN) self.play(ShowCreation(step1_circle), Write(step1_pq), run_time=1) self.wait(1.5) self.play(FadeOut(step1_circle), FadeOut(step1_pq)) # 2. Find the first time it reaches the maximum peak = walk_p.get_arrow_end_point(3) horiz_line = DashedLine(2.5 * LEFT, 2.5 * RIGHT, color=YELLOW) horiz_line.move_to(peak) dot = Dot(color=YELLOW) dot.move_to(peak) step2_pq.next_to(horiz_line, UP) self.play(ShowCreation(horiz_line), DrawBorderThenFill(dot), Write(step2_pq), run_time=1) self.wait(1.5) self.play(FadeOut(horiz_line), FadeOut(step2_pq)) # 3. Split vert_line = DashedLine(2.5 * UP, 2.5 * DOWN, color=YELLOW) vert_line.move_to(peak) step3_pq.next_to(vert_line, DOWN) left_part_p, right_part_p = parts_p self.play(ShowCreation(vert_line), Write(step3_pq), run_time=1) self.play( FadeOut(dot), left_part_p.shift, 0.5 * DOWN + 0.5 * LEFT, right_part_p.shift, DOWN + 0.5 * RIGHT, ) self.wait(1.5) self.play(FadeOut(vert_line), FadeOut(step3_pq)) # 4. Flip the first segment horizontally flip_axis = DashedLine(2 * UP, 2 * DOWN, color=GREY) flip_axis.move_to(left_part_p) step4_pq.next_to(flip_axis, DOWN) self.play( ShowCreation(flip_axis), Write(step4_pq), run_time=1, ) self.play( left_part_p.flip, Animation(flip_axis), ) self.wait(1.5) self.play(FadeOut(step4_pq), FadeOut(flip_axis)) # 5. Put the pieces together step5_pq.move_to(dot) flip_arrow_anims = walk_p.get_flip_arrows_animation(3, color=GREEN) self.play(Write(step5_pq), run_time=1) self.wait(0.5) self.play(flip_arrow_anims, right_part_p.set_color, GREEN) self.wait(0.5) self.play( left_part_p.shift, 1.5 * DOWN + 0.5 * RIGHT, right_part_p.shift, 3 * DOWN + 0.5 * LEFT, Animation(step5_pq), ) self.wait(0.5) self.play(FadeOut(step5_pq)) self.wait(1.5) # Now Reset self.play(FadeOut(walk_p)) self.play(FadeIn(walk_p_copy)) self.wait()
def show_the_solution(self): # Prepare for the solution pre_solve = VGroup(*self.question[::2]) self.play( ReplacementTransform(pre_solve, self.solve), FadeOut(self.question[1]), run_time = 1, ) self.wait() # Manipulate LHS old_l_part, r_part = self.equation new_l_part = ExpTower(order = self.highest_order+1, is_infinite = True) new_l_part.match_height(old_l_part) new_l_part.next_to(r_part, LEFT, aligned_edge = DOWN) old_rect, new_rect = rects = [ CoverRectangle(part, text = "2") for part in (old_l_part, new_l_part.get_exponent()) ] old_two, new_two = twos = [ rect.get_text_mob() for rect in rects ] self.play(DrawBorderThenFill(old_rect, run_time = 1)) self.wait() self.play( ReplacementTransform(old_l_part, new_l_part), ReplacementTransform(old_rect, new_rect), ) self.wait() new_equation = VGroup(new_l_part, r_part, new_rect) new_equation.generate_target() new_equation.target.scale(0.8) new_equation.target.shift(UP) self.play(MoveToTarget(new_equation)) self.wait() # A little bit clean-up source_eq = VGroup(*[ mob.copy() for mob in (new_l_part.get_base(), new_two, r_part[0], r_part[1]) ]) source_eq.generate_target() target_eq = TexMobject("x", "^2", "=", "2") target_eq.scale(3).next_to(source_eq, DOWN, buff = 1) for k, (old_part, new_part) in enumerate(zip(source_eq.target, target_eq)): old_part.move_to(new_part) if k == 1: old_part.scale(0.5) old_part.shift(RIGHT/4) self.play( FadeOut(new_rect), MoveToTarget(source_eq), ) self.wait() # Reveal the final answer result = TexMobject("x", "=", "\\sqrt", "2") result.set_height(source_eq.get_height() * 0.7) result.move_to(source_eq) self.play(*[ ReplacementTransform(source_eq[m], result[n], path_arc = angle) for m, n, angle in [(0, 0, 0), (1, 2, -TAU/3), (2, 1, 0), (3, 3, 0)] ]) self.wait() qed = QEDSymbol() qed.next_to(result, RIGHT, aligned_edge = DOWN, buff = 1.5) self.play(FadeIn(qed)) self.wait()