替换变换前矩形出现

0 投票
1 回答
27 浏览
提问于 2025-04-14 18:05

我正在尝试用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)

1 个回答

1

你对ReplacementTransform的理解确实有些错误。使用ReplacementTransform的意思是这个对象在内存中被替换了。我觉得这个YouTube教程讲得很清楚,虽然它被标记为过时。

这里的问题似乎是,manim在play()函数调用开始时总是显示那些在变换中被替换的对象。一个简单的解决办法是把最后的变换放在一个单独的函数调用里:

        dot_to_slab = ReplacementTransform(blue, blue_slab)
        slab_to_annulus = ReplacementTransform(blue_slab.copy(), blue_annulus)

        self.play(
            LaggedStart(
                *transformations,
                Succession(dot_to_slab),
                lag_ratio=0.9
            )
        )
        self.play(slab_to_annulus)

撰写回答