Esempio n. 1
0
    def scroll_through_patrons(self):
        logo_box = Square(side_length=2.5)
        logo_box.to_corner(DOWN + LEFT, buff=MED_LARGE_BUFF)
        total_width = FRAME_X_RADIUS - logo_box.get_right()[0]

        black_rect = Rectangle(
            fill_color=BLACK,
            fill_opacity=1,
            stroke_width=0,
            width=FRAME_WIDTH,
            height=0.6 * FRAME_HEIGHT,
        )
        black_rect.to_edge(UP, buff=0)
        line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT)
        line.move_to(ORIGIN)
        self.add(line)

        thanks = TextMobject("Funded by the community, with special thanks to:")
        thanks.scale(0.9)
        thanks.next_to(black_rect.get_bottom(), UP, SMALL_BUFF)
        thanks.set_color(YELLOW)
        underline = Line(LEFT, RIGHT)
        underline.scale_to_fit_width(thanks.get_width() + MED_SMALL_BUFF)
        underline.next_to(thanks, DOWN, SMALL_BUFF)
        thanks.add(underline)
        self.add(thanks)

        patrons = VGroup(*map(TextMobject, self.specific_patrons))
        patrons.scale(self.patron_scale_val)
        for patron in patrons:
            if patron.get_width() > self.max_patron_width:
                patron.scale_to_fit_width(self.max_patron_width)
        columns = VGroup(*[
            VGroup(*patrons[i::self.n_patron_columns])
            for i in range(self.n_patron_columns)
        ])
        for column in columns:
            for n, name in enumerate(column):
                name.shift(n * self.name_y_spacing * DOWN)
        columns.arrange_submobjects(
            RIGHT, buff=LARGE_BUFF,
            aligned_edge=UP,
        )
        columns.scale_to_fit_width(total_width - 1)
        columns.next_to(black_rect, DOWN, 3 * LARGE_BUFF)
        columns.to_edge(RIGHT)

        thanks.align_to(columns, alignment_vect=RIGHT)

        self.play(
            columns.move_to, 2 * DOWN, DOWN,
            columns.to_edge, RIGHT,
            Animation(black_rect),
            Animation(line),
            Animation(thanks),
            rate_func=None,
            run_time=self.run_time,
        )
Esempio n. 2
0
 def generate_symbol(self):
     symbol = VGroup(*[
         RegularPolygon(
             n=3, stroke_width=0, fill_color=self.color, fill_opacity=1)
         for i in range(2)
     ])
     symbol.arrange_submobjects(RIGHT, buff=0)
     symbol.set_height(self.inner_radius * 0.7)
     return symbol
Esempio n. 3
0
 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)
Esempio n. 4
0
 def arrange_subparts(self, *subparts):
     for i, piece in enumerate(subparts):
         piece.rotate(i * np.pi / 12, about_point=ORIGIN)
     p1, p2, p3, p4, p5, p6, p7 = subparts
     center_row = VGroup(p1, p4, p7)
     center_row.arrange_submobjects(RIGHT, buff=0)
     for p in p2, p3, p5, p6:
         p.set_width(p1.get_width())
     p2.move_to(p1.get_top(), DOWN + LEFT)
     p3.move_to(p1.get_bottom(), UP + LEFT)
     p5.move_to(p4.get_top(), DOWN + LEFT)
     p6.move_to(p4.get_bottom(), UP + LEFT)
Esempio n. 5
0
    def build_the_equation(self):
        l_part = self.tower.copy()
        r_part = TexMobject("=", "2")
        r_part.match_height(l_part.get_base())
        equation = VGroup(l_part, r_part)
        equation.arrange_submobjects(RIGHT, aligned_edge = DOWN)

        self.play(
            ReplacementTransform(self.tower, l_part, run_time = 1),
            Write(r_part, run_time = 2),
        )
        self.equation = equation
Esempio n. 6
0
 def arrange_subparts(self, *subparts):
     for i, piece in enumerate(subparts):
         piece.rotate(i * np.pi / 12, about_point=ORIGIN)
     p1, p2, p3, p4, p5, p6, p7 = subparts
     center_row = VGroup(p1, p4, p7)
     center_row.arrange_submobjects(RIGHT, buff=0)
     for p in p2, p3, p5, p6:
         p.scale_to_fit_width(p1.get_width())
     p2.move_to(p1.get_top(), DOWN + LEFT)
     p3.move_to(p1.get_bottom(), UP + LEFT)
     p5.move_to(p4.get_top(), DOWN + LEFT)
     p6.move_to(p4.get_bottom(), UP + LEFT)
Esempio n. 7
0
 def generate_symbol(self):
     symbol = VGroup(*[
         Rectangle(
             length=2,
             width=0.5,
             stroke_width=0,
             fill_color=self.color,
             fill_opacity=1,
         ) for i in range(2)
     ])
     symbol.arrange_submobjects(RIGHT, buff=0.5)
     symbol.set_height(self.inner_radius)
     return symbol
Esempio n. 8
0
    def add_words(self):
        # Wallis product
        product = TexMobject(*(["\\text{Wallis公式:}"] + [
            "{%d \\over %d} \\," % (wallis_numer(n), wallis_denom(n))
            for n in range(1, 8)
        ] + ["\\cdots = {\\pi \\over 2}"])).set_color(YELLOW)
        rect = SurroundingRectangle(product, color=YELLOW, buff=0.25)
        wallis_product = VGroup(product, rect)
        wallis_product.set_width(6)

        # All those steps
        nums = [TextMobject("%d. " % k) for k in [1, 2, 3, 4]]
        words = [
            TextMobject(word) for word in [
                "构造合适的矩形边长",
                "同种颜色的矩形的面积之和恒为1",
                "整个图形又像一个${1 \\over 4}$圆,半径是",
                "比较${1 \\over 4}$圆与矩形的面积",
            ]
        ]
        formulae = [
            TextMobject(formula) for formula in [
                "$a_0 = 1,\\, a_n = {1 \\over 2} \cdot {3 \\over 4} \cdots {2n-1 \\over 2n} (n \geq 1)$",
                "$a_0 a_n + a_1 a_{n-1} + \\cdots + a_n a_0 = 1$",
                "$\\begin{aligned} \
                r_n & = a_0 + a_1 + \\cdots + a_{n-1} \\\\ \
                    & = \\textstyle{3 \\over 2} \cdot {5 \\over 4} \cdots {2n-1 \\over 2n-2} \
                    \\quad (n \geq 2) \
                \\end{aligned}$",
                "${1 \\over 4} \\pi {r_n}^2 \\approx n \\quad \\Rightarrow \\quad \\text{Wallis公式}$"
            ]
        ]

        steps = VGroup()
        for num, word, formula in zip(nums, words, formulae):
            num.next_to(word, LEFT)
            formula.next_to(word, DOWN, aligned_edge=LEFT)
            steps.add(VGroup(num, word, formula))
        steps.arrange_submobjects(DOWN, buff=0.6, aligned_edge=LEFT)
        steps.set_width(6)
        steps.next_to(wallis_product, DOWN)
        VGroup(wallis_product, steps).center().to_edge(RIGHT, buff=0.15)

        # Sep line and QED
        sep_line = DashedLine(2 * TOP, 2 * BOTTOM, color=GREY, buff=0.5)
        sep_line.next_to(steps, LEFT)
        qed = QEDSymbol(height=0.570 / 2)
        qed.next_to(steps[-1][-1][-1], RIGHT, aligned_edge=DOWN)

        # Add everything
        self.add(wallis_product, steps, sep_line, qed)
Esempio n. 9
0
    def scroll_through_patrons(self):
        logo_box = Square(side_length=2.5)
        logo_box.to_corner(DOWN + LEFT, buff=MED_LARGE_BUFF)
        total_width = FRAME_X_RADIUS - logo_box.get_right()[0]

        black_rect = Rectangle(fill_color=BLACK,
                               fill_opacity=1,
                               stroke_width=0,
                               width=FRAME_WIDTH,
                               height=1.1 * FRAME_Y_RADIUS)
        black_rect.to_edge(UP, buff=0)
        line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT)
        line.move_to(black_rect, DOWN)
        line.shift(SMALL_BUFF * SMALL_BUFF * DOWN)
        self.add(line)

        patrons = VGroup(*map(TextMobject, self.specific_patrons))
        patrons.scale(self.patron_scale_val)
        for patron in patrons:
            if patron.get_width() > self.max_patron_width:
                patron.scale_to_fit_width(self.max_patron_width)
        columns = VGroup(*[
            VGroup(*patrons[i::self.n_patron_columns])
            for i in range(self.n_patron_columns)
        ])
        for column in columns:
            for n, name in enumerate(column):
                name.shift(n * self.name_y_spacing * DOWN)
        columns.arrange_submobjects(
            RIGHT,
            buff=LARGE_BUFF,
            aligned_edge=UP,
        )
        columns.scale_to_fit_width(total_width - 1)
        columns.next_to(black_rect, DOWN, 3 * LARGE_BUFF)
        columns.to_edge(RIGHT)

        self.play(
            columns.move_to,
            2 * DOWN,
            DOWN,
            columns.to_edge,
            RIGHT,
            Animation(black_rect),
            rate_func=None,
            run_time=self.run_time,
        )
Esempio n. 10
0
 def rewind_and_play_again(self):
     watch_again = TextMobject("再看一遍...")
     watch_again.set_color(YELLOW)
     rewind, play = buttons = VGroup(*[
         Button().get_symbol().set_color(YELLOW).set_height(1)
         for Button in (RewindButton, PlayButton)
     ])
     group = VGroup(watch_again, rewind)
     group.arrange_submobjects(DOWN, aligned_edge = RIGHT)
     group.to_corner(DOWN+RIGHT)
     play.move_to(rewind, aligned_edge = RIGHT)
     self.play(Write(watch_again), run_time = 0.5)
     self.wait()
     self.add(rewind)
     self.words.reverse()
     for word in self.words:
         self.play(FadeOut(VGroup(word)), run_time = 0.2)
         self.wait(0.1)
     self.remove(rewind)
     self.add(play)
     self.play(FadeOut(watch_again), run_time = 0.5)
     self.wait(0.5)
     self.remove(play)
Esempio n. 11
0
 def organize_matrices(self, left, right, result):
     equals = TexMobject("=")
     everything = VGroup(left, right, equals, result)
     everything.arrange_submobjects()
     everything.scale_to_fit_width(FRAME_WIDTH - 1)
     self.add(everything)
Esempio n. 12
0
    def construct(self):
        colors = ["#FF0000", "#FF8000", "#FFFF00", "#00FF00", "#0080FF"]
        wallis_rects_4 = WallisRectangles(
            order=5,
            rect_colors=colors,
        )
        vert_lines = VGroup(*[
            Line(3.5*UP, 3.5*DOWN, color = GREY, stroke_width = 3) \
            .next_to(wallis_rects_4.get_rectangle(0, k), direction, buff = 0)
            for k, direction in zip(list(range(5))+[4], [LEFT]*5+[RIGHT])
        ])
        horiz_lines = VGroup(*[
            Line(3.5*LEFT, 3.5*RIGHT, color = GREY, stroke_width = 3) \
            .next_to(wallis_rects_4.get_rectangle(k, 0), direction, buff = 0)
            for k, direction in zip(list(range(5))+[4], [DOWN]*5+[UP])
        ])
        for vert_line in vert_lines:
            vert_line.vertically_center()
        for horiz_line in horiz_lines:
            horiz_line.horizontally_center()
        vert_labels = VGroup(*[
            TexMobject("a_%d" % k) \
            .move_to((vert_lines[k].get_center() + vert_lines[k+1].get_center())/2) \
            .shift(3.5*DOWN)
            for k in range(5)
        ])
        horiz_labels = VGroup(*[
            TexMobject("a_%d" % k) \
            .move_to((horiz_lines[k].get_center() + horiz_lines[k+1].get_center())/2) \
            .shift(3.5*LEFT)
            for k in range(5)
        ])

        area_texs = VGroup()
        factors = [1.25, 1, 0.9, 0.7, 0.6]
        for p in range(5):
            for q in range(5 - p):
                rect = wallis_rects_4.get_rectangle(p, q)
                tex = TexMobject("{a_%d} {a_%d}" % (q, p))
                tex.scale(factors[p + q])
                tex.move_to(rect)
                area_texs.add(tex)

        figure = VGroup()
        figure.add(wallis_rects_4, vert_lines, horiz_lines, vert_labels,
                   horiz_labels, area_texs)
        figure.to_edge(LEFT)
        self.add(figure)

        tex_list = VGroup()
        for p in range(5):
            formula_string = (
                " + ".join(["a_%d a_%d" % (q, p - q)
                            for q in range(p + 1)]) + "=1")
            formula = TexMobject(formula_string)
            tex_list.add(formula)
        # tex_list.add(TexMobject("\\vdots"))
        tex_factors = np.linspace(1, 0.7, 5)
        for tex, color, factor in zip(tex_list, colors, tex_factors):
            tex.set_color(color)
            tex.scale(factor)
        tex_list.arrange_submobjects(DOWN, aligned_edge=LEFT)
        tex_list.to_edge(RIGHT)
        self.add(tex_list)
        self.wait()
Esempio n. 13
0
    def construct(self):
        # Chart on the left
        colors = [WHITE, ORANGE, GREEN]
        titles = VGroup(*[
            TexMobject(text).set_color(color)
            for text, color in zip(["n", "p_n", "q_n"], colors)
        ])
        contents = VGroup(*[
            VGroup(*[
                TexMobject("%d" % num) for num in
                [k, central_binomial_coeff(k),
                 central_binomial_coeff(k)]
            ]) for k in range(8)
        ])
        titles.arrange_submobjects(RIGHT, buff=1)
        for num, line in enumerate(contents):
            for k, element in enumerate(line):
                buff = 0.6 + 0.8 * num
                element.next_to(titles[k], DOWN, aligned_edge=LEFT, buff=buff)
                element.set_color(colors[k])
        sep_line = Line(ORIGIN, 4.5 * RIGHT, stroke_width=5)
        sep_line.next_to(titles, DOWN)
        chart = VGroup(titles, contents, sep_line)
        chart.set_height(7)
        chart.center().to_edge(LEFT)
        self.add(chart)

        # Figures on the right
        std_zero_pos_axis = NumberLine(x_min=-2,
                                       x_max=2,
                                       color=GREY,
                                       unit_size=0.25,
                                       tick_size=0.05)
        std_zero_pos_axis.rotate(np.pi / 2)
        std_nocross_pos_axis = NumberLine(x_min=-4,
                                          x_max=4,
                                          color=GREY,
                                          unit_size=0.25,
                                          tick_size=0.05)
        std_nocross_pos_axis.rotate(np.pi / 2)
        std_time_axis = NumberLine(x_min=0,
                                   x_max=5.5,
                                   color=GREY,
                                   unit_size=0.25,
                                   tick_size=0.05)
        std_zero_axes = VGroup(std_zero_pos_axis, std_time_axis)
        std_nocross_axes = VGroup(std_nocross_pos_axis, std_time_axis)

        zero_walks = VGroup()
        for sequence in ["UUDD", "UDUD", "UDDU", "DDUU", "DUDU", "DUUD"]:
            axes = std_zero_axes.copy()
            zero_walk = RandomWalk1DArrow(sequence, step_size=0.25)
            zero_walk.move_start_to(axes[0].number_to_point(0))
            zero_walks.add(VGroup(axes, zero_walk))
        zero_walks.arrange_submobjects_in_grid(2, 3, buff=0.5)
        zero_rect = SurroundingRectangle(zero_walks, color=ORANGE, buff=0.4)
        zero_walks.add(zero_rect)

        nocross_walks = VGroup()
        for sequence in ["DDDD", "DDUD", "DDDU", "UUUU", "UUDU", "UUUD"]:
            axes = std_nocross_axes.copy()
            nocross_walk = RandomWalk1DArrow(sequence, step_size=0.25)
            nocross_walk.move_start_to(axes[0].number_to_point(0))
            nocross_walks.add(VGroup(axes, nocross_walk))
        nocross_walks.arrange_submobjects_in_grid(2, 3, buff=0.5)
        nocross_rect = SurroundingRectangle(nocross_walks,
                                            color=GREEN,
                                            buff=0.4)
        nocross_walks.add(nocross_rect)

        relation = TexMobject("p_2", "=", "q_2", "=", "6")
        relation[0].set_color(ORANGE)
        relation[2].set_color(GREEN)
        relation.scale(1.5)
        figure = VGroup(zero_walks, relation, nocross_walks)
        figure.arrange_submobjects(DOWN)
        figure.set_height(7)
        figure.center().to_edge(RIGHT)

        self.add(figure)
        self.wait()
Esempio n. 14
0
class TeacherStudentsScene(PiCreatureScene):
    CONFIG = {
        "student_colors": [BLUE_D, BLUE_E, BLUE_C],
        "student_scale_factor": 0.8,
        "seconds_to_blink": 2,
        "screen_height": 3,
    }

    def setup(self):
        PiCreatureScene.setup(self)
        self.screen = ScreenRectangle(height=self.screen_height)
        self.screen.to_corner(UP + LEFT)
        self.hold_up_spot = self.teacher.get_corner(UP +
                                                    LEFT) + MED_LARGE_BUFF * UP

    def create_pi_creatures(self):
        self.teacher = Mortimer(color=self.default_pi_creature_kwargs["color"])
        self.teacher.to_corner(DOWN + RIGHT)
        self.teacher.look(DOWN + LEFT)
        self.students = VGroup(
            *[Randolph(color=c) for c in self.student_colors])
        self.students.arrange_submobjects(RIGHT)
        self.students.scale(self.student_scale_factor)
        self.students.to_corner(DOWN + LEFT)
        self.teacher.look_at(self.students[-1].eyes)
        for student in self.students:
            student.look_at(self.teacher.eyes)

        return [self.teacher] + list(self.students)

    def get_teacher(self):
        return self.teacher

    def get_students(self):
        return self.students

    def teacher_says(self, *content, **kwargs):
        return self.pi_creature_says(self.get_teacher(), *content, **kwargs)

    def student_says(self, *content, **kwargs):
        if "target_mode" not in kwargs:
            target_mode = random.choice([
                "raise_right_hand",
                "raise_left_hand",
            ])
            kwargs["target_mode"] = target_mode
        student = self.get_students()[kwargs.get("student_index", 1)]
        return self.pi_creature_says(student, *content, **kwargs)

    def teacher_thinks(self, *content, **kwargs):
        return self.pi_creature_thinks(self.get_teacher(), *content, **kwargs)

    def student_thinks(self, *content, **kwargs):
        student = self.get_students()[kwargs.get("student_index", 1)]
        return self.pi_creature_thinks(student, *content, **kwargs)

    def change_all_student_modes(self, mode, **kwargs):
        self.change_student_modes(*[mode] * len(self.students), **kwargs)

    def change_student_modes(self, *modes, **kwargs):
        added_anims = kwargs.pop("added_anims", [])
        self.play(self.get_student_changes(*modes, **kwargs), *added_anims)

    def get_student_changes(self, *modes, **kwargs):
        pairs = zip(self.get_students(), modes)
        pairs = [(s, m) for s, m in pairs if m is not None]
        start = VGroup(*[s for s, m in pairs])
        target = VGroup(*[s.copy().change_mode(m) for s, m in pairs])
        if "look_at_arg" in kwargs:
            for pi in target:
                pi.look_at(kwargs["look_at_arg"])
        submobject_mode = kwargs.get("submobject_mode", "lagged_start")
        return Transform(start,
                         target,
                         submobject_mode=submobject_mode,
                         run_time=2)

    def zoom_in_on_thought_bubble(self,
                                  bubble=None,
                                  radius=FRAME_Y_RADIUS + FRAME_X_RADIUS):
        if bubble is None:
            for pi in self.get_pi_creatures():
                if hasattr(pi, "bubble") and isinstance(
                        pi.bubble, ThoughtBubble):
                    bubble = pi.bubble
                    break
            if bubble is None:
                raise Exception("No pi creatures have a thought bubble")
        vect = -bubble.get_bubble_center()

        def func(point):
            centered = point + vect
            return radius * centered / np.linalg.norm(centered)

        self.play(
            *
            [ApplyPointwiseFunction(func, mob) for mob in self.get_mobjects()])

    def teacher_holds_up(self,
                         mobject,
                         target_mode="raise_right_hand",
                         **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)
        self.play(
            ReplacementTransform(mobject_copy, mobject),
            self.teacher.change,
            target_mode,
        )
class TeacherStudentsScene(PiCreatureScene):
    CONFIG = {
        "student_colors": [BLUE_D, BLUE_E, BLUE_C],
        "teacher_color": GREY_BROWN,
        "student_scale_factor": 0.8,
        "seconds_to_blink": 2,
        "screen_height": 3,
    }

    def setup(self):
        PiCreatureScene.setup(self)
        self.screen = ScreenRectangle(height=self.screen_height)
        self.screen.to_corner(UP + LEFT)
        self.hold_up_spot = self.teacher.get_corner(UP + LEFT) + MED_LARGE_BUFF * UP

    def create_pi_creatures(self):
        self.teacher = Mortimer(color=self.teacher_color)
        self.teacher.to_corner(DOWN + RIGHT)
        self.teacher.look(DOWN + LEFT)
        self.students = VGroup(*[
            Randolph(color=c)
            for c in self.student_colors
        ])
        self.students.arrange_submobjects(RIGHT)
        self.students.scale(self.student_scale_factor)
        self.students.to_corner(DOWN + LEFT)
        self.teacher.look_at(self.students[-1].eyes)
        for student in self.students:
            student.look_at(self.teacher.eyes)

        return [self.teacher] + list(self.students)

    def get_teacher(self):
        return self.teacher

    def get_students(self):
        return self.students

    def teacher_says(self, *content, **kwargs):
        return self.pi_creature_says(
            self.get_teacher(), *content, **kwargs
        )

    def student_says(self, *content, **kwargs):
        if "target_mode" not in kwargs:
            target_mode = random.choice([
                "raise_right_hand",
                "raise_left_hand",
            ])
            kwargs["target_mode"] = target_mode
        student = self.get_students()[kwargs.get("student_index", 1)]
        return self.pi_creature_says(
            student, *content, **kwargs
        )

    def teacher_thinks(self, *content, **kwargs):
        return self.pi_creature_thinks(
            self.get_teacher(), *content, **kwargs
        )

    def student_thinks(self, *content, **kwargs):
        student = self.get_students()[kwargs.get("student_index", 1)]
        return self.pi_creature_thinks(student, *content, **kwargs)

    def change_all_student_modes(self, mode, **kwargs):
        self.change_student_modes(*[mode] * len(self.students), **kwargs)

    def change_student_modes(self, *modes, **kwargs):
        added_anims = kwargs.pop("added_anims", [])
        self.play(
            self.get_student_changes(*modes, **kwargs),
            *added_anims
        )

    def get_student_changes(self, *modes, **kwargs):
        pairs = zip(self.get_students(), modes)
        pairs = [(s, m) for s, m in pairs if m is not None]
        start = VGroup(*[s for s, m in pairs])
        target = VGroup(*[s.copy().change_mode(m) for s, m in pairs])
        if "look_at_arg" in kwargs:
            for pi in target:
                pi.look_at(kwargs["look_at_arg"])
        submobject_mode = kwargs.get("submobject_mode", "lagged_start")
        return Transform(
            start, target,
            submobject_mode=submobject_mode,
            run_time=2
        )

    def zoom_in_on_thought_bubble(self, bubble=None, radius=FRAME_Y_RADIUS + FRAME_X_RADIUS):
        if bubble is None:
            for pi in self.get_pi_creatures():
                if hasattr(pi, "bubble") and isinstance(pi.bubble, ThoughtBubble):
                    bubble = pi.bubble
                    break
            if bubble is None:
                raise Exception("No pi creatures have a thought bubble")
        vect = -bubble.get_bubble_center()

        def func(point):
            centered = point + vect
            return radius * centered / np.linalg.norm(centered)
        self.play(*[
            ApplyPointwiseFunction(func, mob)
            for mob in self.get_mobjects()
        ])

    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 organize_matrices(self, left, right, result):
     equals = TexMobject("=")
     everything = VGroup(left, right, equals, result)
     everything.arrange_submobjects()
     everything.scale_to_fit_width(FRAME_WIDTH - 1)
     self.add(everything)