线以意外缩放旋转

The line rotate with unexpected scaling

场景很简单,一行并旋转PI/2,代码如下:

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

但是,在旋转的过程中,貌似在缩放的同时,我检查了轴是[0 0 1]也就是z轴,我想线的长度应该保持不变。

如何防止线路结垢?谢谢!

使用RotateRotating,参见this

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()

应该很清楚的一点是,当你定义一个更新函数时,使用 dtalpha 是不一样的.即定义

不一样
        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.

其中self指的是Sceneclass。 而alpha是从0到1变化的,其实你可以把之前的场景写成这个update方法,得到的结果是一样的:

        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)