You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Manim中VGroup无法执行FadeOut动画的问题求助

Manim中VGroup应用FadeOut失效的原因解析

问题场景

用Manim制作马尔可夫链动画时,需要先让整个马尔可夫链淡出,再显示next_step元素。将链中所有元素打包进VGroup(chain)后,对其调用FadeOut动画无效果,但ReplaceTransform等变换对该VGroup有效。后续通过AnimationGroup分组执行动画解决了问题,但想知道原方法失效的原因。

原代码

from manim import *
import numpy as np

class MarkovChain(Scene):
    def construct(self):

        # creating objects
        circles = [Circle(radius=0.8, color=WHITE) for _ in range(4)]
        texts = [Text(f"S{i}", font='Comfortaa') for i in range(1, 5)]
        probabilities = ['0.7', '0.3', '0.5', '0.5', '1.0']
        probs = [Text(p, font='Comfortaa', font_size=35) for p in probabilities]

        # position circles
        circles[0].move_to(UL*3).shift(LEFT)            
        circles[1].move_to(UL*3).shift(RIGHT*4)         
        mid = midpoint(circles[0].get_center(), circles[1].get_center())
        circles[2].move_to(mid).shift(DOWN*3)           
        circles[3].move_to(mid).shift(DOWN*3).shift(RIGHT*5)
        VGroup(*circles).shift(DOWN)

        # text in circles
        for s, c in zip(texts, circles):
            s.move_to(c.get_center())

        # arrows
        arrow_pos = [
            (0, 1, 0, 180),
            (0, 2, 315, 135),
            (2, 1, 45, 225),
            (2, 3, 0, 180),
            (1, 3, 315, 135),
        ]
        arrows = [
            Arrow(
                start=circles[i].point_at_angle(fr*DEGREES),
                end=circles[j].point_at_angle(to*DEGREES)
            )
            for i, j, fr, to in arrow_pos
        ]

        # directions for probs
        dirs = {
            0: UP,
            3: UP,
            1: LEFT,
            2: LEFT,
        }

        for i, (arrow, prob) in enumerate(zip(arrows, probs)):
            direction = dirs.get(i, RIGHT)
            prob.next_to(arrow.get_center(), direction=direction, buff=0.25)

        chain = VGroup(*arrows, *circles, *texts, *probs)
        next_step = VGroup(texts[1], circles[1])

        # 问题所在的动画调用
        self.play(FadeOut(*chain),
                  FadeIn(next_step),
                  run_time=2)
        
        self.wait(3)

临时解决方案

通过AnimationGroup分组执行淡出动画,避免与淡入动画冲突:

# 拆分动画,先执行所有元素的淡出
animations_out = [
        FadeOut(*arrows),
        FadeOut(*probs),
        FadeOut(*texts),
        FadeOut(*circles)
    ]

self.play(AnimationGroup(*animations_out, lag_ratio=0.0))
# 再执行next_step的淡入
self.play(FadeIn(next_step))

失效原因解析

核心问题是同一动画帧中对同一个Mobject同时执行了相反的动画操作,导致逻辑冲突:

  • next_step包含的texts[1]和circles[1],同时属于chain VGroup。
  • 原代码在同一个self.play调用中,同时执行FadeOut(*chain)(让所有元素包括这两个元素透明度降至0)和FadeIn(next_step)(让这两个元素透明度升至1)。
  • Manim的动画系统会合并同一Mobject的多个动画,对于透明度这类数值属性,两个相反的插值动画会相互抵消,最终这两个元素的透明度保持不变。
  • 若视觉焦点集中在这两个元素上,会让你误以为整个FadeOut动画失效;部分Manim版本中,这种冲突还可能影响整个动画组的执行逻辑。

而AnimationGroup的解决方案有效,是因为它先单独完成所有元素的淡出动画,再执行next_step的淡入,从根本上避免了同一Mobject的动画冲突。

内容的提问来源于stack exchange,提问作者Yulia Demutskaia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 19:09:50