diff --git a/example_scenes.py b/example_scenes.py index 0a3efb46..181879b5 100644 --- a/example_scenes.py +++ b/example_scenes.py @@ -277,37 +277,70 @@ class TexTransformExample(Scene): 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) + + # 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) + + 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(decimal.next_to, square) - # This ensures thst decimal.set_value(square.get_y()) is - # called every frame - f_always(decimal.set_value, square.get_y) + always(label.next_to, brace, UP) + # You could also write the following equivalent line + # label.add_updater(lambda m: m.next_to(brace, UP)) - self.add(square, decimal) + # 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() - # You can also add any function generally to a Mobject's - # list of 'updaters'. + # 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) class SurfaceExample(Scene): @@ -435,7 +468,7 @@ class ControlsExample(Scene): self.add(MotionMobject(text)) self.textbox.set_value("Manim") - # self.embed() + self.embed() # See https://github.com/3b1b/videos for many, many more