0

The scene is simple, one Line and rotate PI/2 with below code:

ln = Line(ORIGIN, RIGHT*2)
self.add(ln)
self.wait()
self.play(ApplyMethod(ln.rotate, PI/2, OUT))

However, during the rotating, seemingly scaling at the same time, I check the axis is [0 0 1] that is z axis, I suppose the length of the line should be kept unchanged.

How to prevent the line from scaling? Thanks!

4

1 回答 1

5

使用RotateRotating,请参阅

class RotateVector(Scene):
    def construct(self):
        coord_start=[1,1,0]
        coord_end=[2,3,0]
        dot_start=Dot().move_to(coord_start)
        dot_end=Dot().move_to(coord_end)
        vector=Arrow(coord_start,coord_end,buff=0)
        vector.set_color(RED)

        self.add(dot_start,dot_end)
        self.play(GrowArrow(vector))

        self.play(
            Rotating(
                        vector,
                        radians=PI*2,
                        about_point=coord_start,
                        rate_func=smooth,
                        run_time=1
                    )
        )
        self.wait()
        self.play(
            Rotating(
                        vector,
                        radians=PI*2,
                        about_point=coord_end,
                        rate_func=linear,
                        run_time=1
                    )
        )
        self.wait()

编辑

您可以创建自定义动画:

class RotatingAndMove(Animation):
    CONFIG = {
        "axis": OUT,
        "radians": TAU,
        "run_time": 5,
        "rate_func": linear,
        "about_point": None,
        "about_edge": None,
    }
    def __init__(self, mobject, direction,**kwargs):
        assert(isinstance(mobject, Mobject))
        digest_config(self, kwargs)
        self.mobject = mobject
        self.direction = direction

    def interpolate_mobject(self, alpha):
        self.mobject.become(self.starting_mobject)
        self.mobject.rotate(
            alpha * self.radians,
            axis=self.axis,
            about_point=self.about_point,
            about_edge=self.about_edge,
        )
        self.mobject.shift(alpha*self.direction)

class NewSceneRotate(Scene):
    def construct(self):
        arrow=Vector(UP)
        arrow.to_corner(UL)
        self.play(GrowArrow(arrow))
        self.play(
                RotatingAndMove(arrow,RIGHT*12+DOWN*4)
            )
        self.wait()

或者您可以使用UpdateFromAlphaFunc

class NewSceneRotateUpdate(Scene):
    def construct(self):
        arrow=Vector(UP)
        arrow.to_corner(UL)

        direction=RIGHT*12+DOWN*4
        radians=TAU
        arrow.starting_mobject=arrow.copy()

        def update_arrow(mob,alpha):
            mob.become(mob.starting_mobject)
            mob.rotate(alpha*radians)
            mob.shift(alpha*direction)

        self.play(GrowArrow(arrow))
        self.play(
                UpdateFromAlphaFunc(arrow,update_arrow,rate_func=linear,run_time=5)
            )
        self.wait()

应该非常清楚的是,当您定义更新函数时,使用dt作为alpha是不一样的。也就是定义不一样

        def update_function(mob,dt)

作为

        def update_function(mob,alpha)

dt随视频的 fps 而变化,计算如下:

dt = 1/self.camera.frame_rate
# You don't have to calculate it, manim already does it by default,
# I just write it so you know where it comes from.

whereselfScene类。而alpha从0变化到1,其实可以用这个更新方法写previus场景,得到同样的结果:

        def update_arrow(mob,dt):
            alpha=interpolate(0,1,dt)
            mob.become(mob.starting_mobject)
            mob.rotate(alpha*radians)
            mob.shift(alpha*direction)

如果您希望 alpha 在不同的时间间隔内变化,这可能很有用,请使用

            alpha=interpolate(alpha_start,alpha_end,dt)
于 2019-08-05T19:19:18.610 回答