mirror of
https://github.com/3b1b/manim.git
synced 2025-09-19 04:41:56 +00:00
Update changed example scenes in docs
This commit is contained in:
parent
3c0f8abe5f
commit
9b3332ad02
3 changed files with 101 additions and 24 deletions
Binary file not shown.
Binary file not shown.
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue