diff --git a/_sources/getting_started/example_scenes.rst.txt b/_sources/getting_started/example_scenes.rst.txt index c45258ae..8a7c0a33 100644 --- a/_sources/getting_started/example_scenes.rst.txt +++ b/_sources/getting_started/example_scenes.rst.txt @@ -103,14 +103,22 @@ TexTransformExample class TexTransformExample(Scene): def construct(self): - kw = { - "isolate": ["B", "C", "=", "(", ")"] - } + to_isolate = ["B", "C", "=", "(", ")"] lines = VGroup( + # Surrounding substrings with double braces + # will ensure that those parts are separated + # out in the Tex. For example, here the + # Tex will have 5 submobjects, corresponding + # to the strings [A^2, +, B^2, =, C^2] Tex("{{A^2}} + {{B^2}} = {{C^2}}"), Tex("{{A^2}} = {{C^2}} - {{B^2}}"), - Tex("{{A^2}} = (C + B)(C - B)", **kw), - Tex("A = \\sqrt{(C + B)(C - B)}", **kw) + # Alternatively, you can pass in the keyword argument + # "isolate" with a list of strings that should be out as + # their own submobject. So both lines below are equivalent + # to what you'd get by wrapping every instance of "B", "C" + # "=", "(" and ")" with double braces + Tex("{{A^2}} = (C + B)(C - B)", isolate=to_isolate), + Tex("A = \\sqrt{(C + B)(C - B)}", isolate=to_isolate) ) lines.arrange(DOWN, buff=LARGE_BUFF) for line in lines: @@ -122,6 +130,11 @@ TexTransformExample play_kw = {"run_time": 2} self.add(lines[0]) + # The animation TransformMatchingTex will line up parts + # of the source and target which have matching tex strings. + # Here, giving it a little path_arc makes each part sort of + # rotate into their final positions, which feels appropriate + # for the idea of rearranging an equation self.play( TransformMatchingTex( lines[0].copy(), lines[1], @@ -131,11 +144,17 @@ TexTransformExample ) self.wait() + # Now, we could try this again on the next line... self.play( TransformMatchingTex(lines[1].copy(), lines[2]), **play_kw ) self.wait() + # ...and this looks nice enough, but since there's no tex + # in lines[2] which matches "C^2" or "B^2", those terms fade + # out to nothing while the C and B terms fade in from nothing. + # If, however, we want the C^2 to go to C, and B^2 to go to B, + # we can specify that with a key map. self.play(FadeOut(lines[2])) self.play( TransformMatchingTex( @@ -149,18 +168,37 @@ TexTransformExample ) self.wait() + # And to finish off, a simple TransformMatchingShapes would work + # just fine. But perhaps we want that exponent on A^2 to transform into + # the square root symbol. At the moment, lines[2] treats the expression + # A^2 as a unit, so we might create a new version of the same line which + # separates out just the A. This way, when TransformMatchingTex lines up + # all matching parts, the only mismatch will be between the "^2" from + # new_line2 and the "\sqrt" from the final line. By passing in, + # transform_mismatches=True, it will transform this "^2" part into + # the "\sqrt" part. + new_line2 = Tex("{{A}}^2 = (C + B)(C - B)", isolate=to_isolate) + new_line2.replace(lines[2]) + new_line2.match_style(lines[2]) + self.play( TransformMatchingTex( - lines[2].copy(), lines[3], - fade_transform_mismatches=True, + new_line2, lines[3], + transform_mismatches=True, ), **play_kw ) self.wait(3) self.play(FadeOut(lines, RIGHT)) - source = TexText("the morse code") - target = TexText("here come dots") + # Alternatively, if you don't want to think about breaking up + # the tex strings deliberately, you can TransformMatchingShapes, + # which will try to line up all pieces of a source mobject with + # those of a target, regardless of the submobject hierarchy in + # each one, according to whether those pieces have the same + # shape (as best it can). + source = Text("the morse code", height=1) + target = Text("here come dots", height=1) self.play(Write(source)) self.wait() @@ -186,34 +224,73 @@ UpdatersExample class UpdatersExample(Scene): def construct(self): - decimal = DecimalNumber( - 0, - show_ellipsis=True, - num_decimal_places=3, - include_sign=True, - ) square = Square() - square.to_edge(UP) + square.set_fill(BLUE_E, 1) - always(decimal.next_to, square) - f_always(decimal.set_value, square.get_y) + # On all all frames, the constructor Brace(square, UP) will + # be called, and the mobject brace will set its data to match + # that of the newly constructed object + brace = always_redraw(Brace, square, UP) - self.add(square, decimal) + text, number = label = VGroup( + Text("Width = "), + DecimalNumber( + 0, + show_ellipsis=True, + num_decimal_places=2, + include_sign=True, + ) + ) + label.arrange(RIGHT) + + # This ensures that the method deicmal.next_to(square) + # is called on every frame + always(label.next_to, brace, UP) + # You could also write the following equivalent line + # label.add_updater(lambda m: m.next_to(brace, UP)) + + # If the argument itself might change, you can use f_always, + # for which the arguments following the initial Mobject method + # should be functions returning arguments to that method. + # The following line ensures thst decimal.set_value(square.get_y()) + # is called every frame + f_always(number.set_value, square.get_width) + # You could also write the following equivalent line + # number.add_updater(lambda m: m.set_value(square.get_width())) + + self.add(square, brace, label) + + # Notice that the brace and label track with the square self.play( - square.to_edge, DOWN, + square.scale, 2, + rate_func=there_and_back, + run_time=2, + ) + self.wait() + self.play( + square.set_width, 5, {"stretch": True}, run_time=3, ) - self.play(square.center) + self.wait() + self.play( + square.set_width, 2, + run_time=3 + ) self.wait() + # In general, you can alway call Mobject.add_updater, and pass in + # a function that you want to be called on every frame. The function + # should take in either one argument, the mobject, or two arguments, + # the mobject and the amount of time since the last frame. now = self.time + w0 = square.get_width() square.add_updater( - lambda m: m.set_y(math.sin(self.time - now)) + lambda m: m.set_width(w0 * math.cos(self.time - now)) ) - self.wait(10) + self.wait(4 * PI) The new classes and usage in this scene are ``DecimalNumber``, ``.to_edge()``, -``.center()``, ``always()``, ``f_always()``, ``.set_y()`` and ``.add_updater()``. +``.center()``, ``always_become()``, ``always()``, ``f_always()``, ``.set_y()`` and ``.add_updater()``. - ``DecimalNumber`` is a variable number, speed it up by breaking it into ``Tex`` characters. - ``.to_edge()`` means to place the object on the edge of the screen. diff --git a/_static/example_scenes/TexTransformExample.mp4 b/_static/example_scenes/TexTransformExample.mp4 index 81c1f486..2dbac232 100644 Binary files a/_static/example_scenes/TexTransformExample.mp4 and b/_static/example_scenes/TexTransformExample.mp4 differ diff --git a/_static/example_scenes/UpdatersExample.mp4 b/_static/example_scenes/UpdatersExample.mp4 index af86f07f..f20c48b9 100644 Binary files a/_static/example_scenes/UpdatersExample.mp4 and b/_static/example_scenes/UpdatersExample.mp4 differ diff --git a/development/about.html b/development/about.html index ff7a54a2..9ea14302 100644 --- a/development/about.html +++ b/development/about.html @@ -8,8 +8,8 @@ - - + +