英文:
In Manim, how can I combine FadeIn and FadeOut in one animation?
问题
我正在尝试创建一个动画,该动画会将MathTex
淡入然后淡出,同时文本会在整个动画过程中进行缩放并改变其位置。
我知道可以像这样制作它,使用两个具有ReplacementTransform的动画:
txt_3_start = MathTex(
"3",
color=RED,
font_size=1,
).set_opacity(0)
txt_3_middle = MathTex(
"3",
color=GREEN,
stroke_width=f_z_stroke_width,
font_size=1 * 1.5,
).shift(RIGHT).set_opacity(1)
txt_3_end = MathTex(
"3",
color=BLUE,
font_size=1 * 1.5 * 1.5,
).shift(2 * RIGHT).set_opacity(0)
self.play(
ReplacementTransform(txt_3_start, txt_3_middle, rate_func=linear),
)
self.play(
ReplacementTransform(txt_3_middle, txt_3_end, rate_func=linear),
)
这样可以正常工作并具有所需的效果。
但是,我还希望同时播放另一个动画,例如一个正在绘制的正方形。因此,我尝试将前两个动画合并为一个动画,使用Succession
,像这样:
txt_3_anim = Succession(
ReplacementTransform(txt_3_start, txt_3_middle, rate_func=linear),
ReplacementTransform(txt_3_middle, txt_3_end, rate_func=linear),
)
my_square = Square(color=RED, fill_opacity=1, fill_color=BLUE)
self.play(
Write(my_square),
txt_3_anim
)
但是当我这样做时,出现了意外的行为:txt_3_middle
在整个动画过程中都会出现,从开始到结束。
我已经尝试过使用目标和animate函数等替代方法,但仍然遇到相同的问题。有谁可以帮忙吗?谢谢!
英文:
I'm trying to create an animation that fades in a MathTex
and then fades it out, as the text scales up and shifts its position throughout the whole animation.
I know I could make it like this, using two animations with ReplacementTransform:
txt_3_start = MathTex(
"3",
color=RED,
font_size = 1,
).set_opacity(0)
txt_3_middle = MathTex(
"3",
color=GREEN,
stroke_width = f_z_stroke_width,
font_size= 1 * 1.5,
).shift(RIGHT).set_opacity(1)
txt_3_end = MathTex(
"3",
color=BLUE,
font_size= 1 * 1.5 * 1.5,
).shift(2*RIGHT).set_opacity(0)
self.play(
ReplacementTransform(txt_3_start, txt_3_middle, rate_func=linear),
)
self.play(
ReplacementTransform(txt_3_middle, txt_3_end, rate_func=linear),
)
This works fine and has the desired effect.
However I also want another animation to play at the same time, for example a square being written. Therefore, I tried to do the previous two animations in just one animation using Succession
like this:
txt_3_anim = Succession(
ReplacementTransform(txt_3_start, txt_3_middle, rate_func=linear),
ReplacementTransform(txt_3_middle, txt_3_end, rate_func=linear),
)
my_square = Square(color = RED, fill_opacity=1, fill_color = BLUE)
self.play(
Write(my_square),
txt_3_anim
)
But when I do that, I get an unexpected behaviour: txt_3_middle
appears throughout the whole animation, since it starts until it ends.
I have tried alternatives like using targets and the animate function, but I keep getting the same problem.
Can anyone help? Thanks!
答案1
得分: 1
Succession()
有意外的行为。它将场景中所有与您传递给它的任何动画相关的对象添加到场景中(除非这些对象是“引入动画”的一部分,这些动画显示对象的创建)。
由于您的动画不是“引入”类型,所以Succession()
会将对象txt_3_start
、txt_3_middle
和txt_3_end
添加到场景中。第一个和最后一个由于opacity=0
而不可见,但中间的对象的opacity=1
,因此它是可见的。
我无法想出在不遇到这个问题的情况下使用Succession()
的方法。如果将中间对象设置为透明,那么任何变换都不会产生可见的输出,因为所有相关对象都是不可见的。
您可以为将一个对象转换为另一个对象,然后再转换为另一个对象编写自己的Animation
类。但对于这种特定情况来说,这种解决方案可能过于复杂。
可以在此处使用的更简单的解决方案是在两个单独的self.play()
中播放两个转换,并同时使用一个用于创建正方形的更新器。像这样:
有一个小助手函数,隐藏在manim中,叫做turn_animation_into_updater()
,它可以用来创建更新器,而无需编写它。
# 创建将写入正方形的更新器
my_square = Square(color=RED, fill_opacity=1, fill_color=BLUE)
self.add(my_square)
turn_animation_into_updater(Write(my_square, run_time=2))
# 更新器将在`self.play()`或`self.wait()`调用期间运行
self.play(
ReplacementTransform(txt_3_start, txt_3_middle, rate_func=linear),
)
self.play(
ReplacementTransform(txt_3_middle, txt_3_end, rate_func=linear),
)
这会产生预期的动画(我将您在示例中使用的字体大小更改为50,以使文本在这里可见):
英文:
Succession()
has that unexpected behaviour. It adds to the scene all objects involved in any of the animations you pase to it (except if those object are part of a "introduction animation", which are those which show the creation of objects).
Since your animations are not of type "introduction", then Succession()
adds to the scene the objects txt_3_start
, txt_3_middle
, and txt_3_end
. The first and last are not visible due to opacity=0, but the middle one has opacity=1 and thus it is visible.
I cannot think any way of using Succession()
without running into this problem. If you make the middle object transparent, then any of the transformations will produce any visible output, since all involved objects are invisible.
You may write your own Animation
class for transforming one object into another, and then into another. But that solution may be overkill for this particular case.
A simpler solution that can be used here is to play your two transformations in two separate self.play()
, as in your first code, and at the same time use an updater for the creation of the square. Like this:
There is a little helper function, hidden in manim, called turn_animation_into_updater()
which can be used to create an updater without needing to write it.
# Create the updater which will write the square
my_square = Square(color = RED, fill_opacity=1, fill_color = BLUE)
self.add(my_square)
turn_animation_into_updater(Write(my_square, run_time=2))
# the updater will be run during the `self.play()` or `self.wait()` calls
self.play(
ReplacementTransform(txt_3_start, txt_3_middle, rate_func=linear),
)
self.play(
ReplacementTransform(txt_3_middle, txt_3_end, rate_func=linear),
)
)
# the updater is automatically removed when Write() finishes
This produces the intended animation (I changed the font size you used in your example to 50, to make the text visible here):
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论