Manim中ReplacementTransform使用疑问:蓝色矩形提前显示
问题
我正在尝试用Manim复刻谷歌Logo,目前遇到的问题是蓝色矩形在ReplacementTransform变换前就已显示。我对ReplacementTransform的理解是,目标对象在变换前不会出现,而是随着动画推进逐步显现,但我的场景中蓝色矩形却提前出现了。请问我的理解是否正确,还是用法有误?
代码示例
from manim import * class Props: blue = "#4285F4" red = "#DB4437" yellow = "#F4B400" green = "#0F9D58" dot_radius = 0.5 arc_inner_radius = 1 arc_outer_radius = 1.5 arc_angle = PI / 2 blue_start_angle = -PI / 4 red_start_angle = -7 * PI / 4 yellow_start_angle = -5 * PI / 4 green_start_angle = -3 * PI / 4 class GoogleLogo(Scene): def create_dot(self, color, radius, **kwargs): return Dot(color=color, radius=radius, **kwargs) def arrange_dots(self, blue, red, yellow, green): blue.move_to((-3, 0, 0)) red.move_to((-1, 0, 0)) yellow.move_to((1, 0, 0)) green.move_to((3, 0, 0)) def annulus_sector( self, color, start_angle, angle=PI / 2, inner_radius=Props.arc_inner_radius, outer_radius=Props.arc_outer_radius, ): return AnnularSector( inner_radius=inner_radius, outer_radius=outer_radius, color=color, fill_opacity=1.0, start_angle=start_angle, angle=angle, stroke_width=0, ) def construct(self): blue, red, green, yellow = [ self.create_dot(c, Props.dot_radius) for c in (Props.blue, Props.red, Props.green, Props.yellow) ] self.arrange_dots(blue, red, yellow, green) dots = VGroup(blue, red, yellow, green) bounce_animation = [ AnimationGroup( x.animate(rate_func=there_and_back).shift(UP * 0.5), x.animate(rate_func=there_and_back).shift(DOWN * 0.5), ) for x in dots ] for _ in range(1): self.play(LaggedStart(*bounce_animation, lag_ratio=0.1)) # transform dots to letter G blue_annulus, red_annulus, yellow_annulus, green_annulus = [ self.annulus_sector(c, a, ang) for c, a, ang in zip( [Props.blue, Props.red, Props.yellow, Props.green], [ Props.blue_start_angle, Props.red_start_angle, Props.yellow_start_angle, Props.green_start_angle, ], [PI / 4] + [PI / 2] * 3, ) ] dots_minus_blue = VGroup(red, yellow, green) sectors_minus_blue = VGroup(red_annulus, yellow_annulus, green_annulus) transformations = [ ReplacementTransform(dot, sect, path_func=utils.paths.path_along_arc(-PI)) for dot, sect in zip(dots_minus_blue, sectors_minus_blue) ] blue_slab = Rectangle(height=0.5, width=1.5, color=Props.blue, fill_opacity=1) blue_slab.next_to(blue_annulus, UP, aligned_edge=UR, buff=0) blue_slab.set_stroke(width=0) blue_slab.shift(UP * 0.1) blue_annulus.set_stroke(width=0) dot_to_slab = ReplacementTransform(blue, blue_slab) slab_to_annulus = ReplacementTransform(blue_slab.copy(), blue_annulus) self.play( LaggedStart( *transformations, Succession(dot_to_slab, slab_to_annulus), lag_ratio=0.9 ) ) self.wait(3)
解答
你的理解完全正确:ReplacementTransform的目标对象本应在动画开始前隐藏,随动画进程逐步替换源对象。问题出在两个地方:
- 目标对象初始可见:Manim中所有创建的Mobject默认都是可见状态,你创建
blue_slab后没有手动隐藏,导致它提前出现在场景中。 - 不必要的对象复制:你用
blue_slab.copy()做第二次变换,复制出的对象同样默认可见,会和原矩形重叠,进一步加剧提前显示的问题。
修正步骤
- 创建
blue_slab和blue_annulus后,立即设置它们为隐藏状态:set_opacity(0) - 第二次变换直接使用原
blue_slab,不需要复制,ReplacementTransform会自动处理对象的过渡
修改后的关键代码片段:
blue_slab = Rectangle(height=0.5, width=1.5, color=Props.blue, fill_opacity=1) blue_slab.next_to(blue_annulus, UP, aligned_edge=UR, buff=0) blue_slab.set_stroke(width=0) blue_slab.shift(UP * 0.1) blue_slab.set_opacity(0) # 初始隐藏蓝色矩形 blue_annulus.set_stroke(width=0) blue_annulus.set_opacity(0) # 初始隐藏蓝色扇形 dot_to_slab = ReplacementTransform(blue, blue_slab) slab_to_annulus = ReplacementTransform(blue_slab, blue_annulus) # 移除copy()
ReplacementTransform会在动画启动时自动恢复目标对象的不透明度,完成从源到目标的平滑过渡,这样就不会出现提前显示的问题了。
内容的提问来源于stack exchange,提问作者monte
相关产品推荐
相关产品推荐

