跳转至

为变化添加动画

影片代码
import manimgx as m


class AnimateHero(m.Scene):
    def construct(self) -> None:
        square = m.Square(color=m.BLUE, fill_opacity=0.5)
        self.play(m.Create(square))
        self.play(square.animate.shift(3 * m.RIGHT).set_color(m.YELLOW))
        self.play(square.animate(run_time=2).rotate(m.PI / 2).scale(0.5))
        self.play(square.animate.move_to(m.ORIGIN).set_color(m.BLUE))

square.shift(m.RIGHT) 一次性移动正方形。square.animate.shift(m.RIGHT) 创建一个 移动它的动画:将其传给 play,正方形便在动画的运行时间内移动。在 .animate 后链式 调用多个方法,它们会同时发生。将动画关键字传给 .animate,即 square.animate(run_time=2),来为其计时。

.animate 从动画开始时 mobject 的当前状态变化到调用结束后 mobject 的状态:每个点沿 直线行进,除非你给定一个 path_arc。

animate

代码
import manimgx as m


class MobjectAnimateExample(m.Scene):
    def construct(self) -> None:
        triangle = m.Triangle(color=m.BLUE, fill_opacity=0.5)
        self.add(triangle)
        self.play(triangle.animate.shift(3 * m.LEFT).scale(1.5))
        self.play(triangle.animate.rotate(m.PI).set_color(m.YELLOW))
        self.play(triangle.animate(path_arc=m.PI).move_to(3 * m.RIGHT))

mobject 的动画,由在其上执行的方法调用构建。

square.animate.shift(RIGHT).scale(2) 是一个将方形向右移动 并加倍其尺寸的动画:将其传给 Scene.play。每个 调用被记录——并在拷贝上立即尝试,因此错误的调用在书写处 失败——并返回该动画,因此调用可链式书写。调用在动画开始时 对 mobject 当时的状态执行,动画将其从该状态 补间到结果:在 Succession(square.animate.shift(RIGHT), square.animate.rotate(PI / 2)) 中, 方形在 shift 留下它的位置绕其中心旋转。当动画 完成时,调用对 mobject 本身执行。

运动遵循调用:其中的旋转($rotate、flip)使 mobject 绕其枢轴刚性地旋转整个角度(rotate(TAU) 为整圈);其他每个调用使其中心 直线移动;其余变化(尺寸、颜色、新形状)沿路径 混合。在任何方法之前用选项调用 animate—— square.animate(run_time=2, rate_func=linear).shift(UP)——以设置 动画的 Transform options;其中的 path_arc 或 path_func 替代运动。用函数调用它—— square.animate(lambda s: s.shift(UP))——以记录该函数为 一个调用。如此调用你自己的方法:通过 animate,类型检查器 只知道 ManimGX 的方法,但它会根据 mobject 的 类检查函数。

mobject.animate
源码

manimgx\mobject.py

def animate(self) -> "Animate[Self]":
    """mobject 的动画,由在其上执行的方法调用构建。

    `square.animate.shift(RIGHT).scale(2)` 是一个将方形向右移动
    并加倍其尺寸的动画:将其传给 [Scene.play][manimgx.Scene.play]。每个
    调用被记录——并在拷贝上立即尝试,因此错误的调用在书写处
    失败——并返回该动画,因此调用可链式书写。调用在动画开始时
    对 mobject 当时的状态执行,动画将其从该状态
    补间到结果:在
    `Succession(square.animate.shift(RIGHT), square.animate.rotate(PI / 2))` 中,
    方形在 shift 留下它的位置绕其中心旋转。当动画
    完成时,调用对 mobject 本身执行。

    运动遵循调用:其中的旋转(`$rotate`、`flip`)使
    mobject 绕其枢轴刚性地旋转整个角度(`rotate(TAU)` 为整圈);其他每个调用使其中心
    直线移动;其余变化(尺寸、颜色、新形状)沿路径
    混合。在任何方法之前用选项调用 `animate`——
    `square.animate(run_time=2, rate_func=linear).shift(UP)`——以设置
    动画的 [Transform options][manimgx.animation.transform.TransformOptions];其中的
    `path_arc` 或 `path_func` 替代运动。用函数调用它——
    `square.animate(lambda s: s.shift(UP))`——以记录该函数为
    一个调用。如此调用你自己的方法:通过 `animate`,类型检查器
    只知道 ManimGX 的方法,但它会根据 mobject 的
    类检查函数。

    Examples:
        ```python
        import manimgx as m


        class MobjectAnimateExample(m.Scene):
            def construct(self) -> None:
                triangle = m.Triangle(color=m.BLUE, fill_opacity=0.5)
                self.add(triangle)
                self.play(triangle.animate.shift(3 * m.LEFT).scale(1.5))
                self.play(triangle.animate.rotate(m.PI).set_color(m.YELLOW))
                self.play(triangle.animate(path_arc=m.PI).move_to(3 * m.RIGHT))
        ```
    """
    from manimgx.animation.transform import Animate

    return Animate(self)

Animate

代码
import manimgx as m


class AnimateExample(m.Scene):
    def construct(self) -> None:
        bar = m.Rectangle(width=3, height=1, color=m.BLUE, fill_opacity=0.5)
        self.add(bar.shift(4 * m.LEFT))
        self.play(
            bar.animate(run_time=2)
            .shift(8 * m.RIGHT)
            .rotate(m.PI / 2)
            .set_color(m.YELLOW)
        )

mobject 方法调用的动画。

它是 mobject.animate 的返回值。像在 mobject 上 一样调用其方法,square.animate.shift(RIGHT).scale(2),然后播放它:它就是 该动画。每个调用都会被记录,并立即在副本上尝试,因此错误的调用会在其书写 处失败;这些调用会在动画开始时(在 Succession 中, 在它之前的部分之后)按 mobject 当时的状态执行。当它结束时,mobject 恰好 是这些调用所产生的结果。

mobject 随调用的执行而移动:其中的一次旋转(rotate、flip)会将其刚性地 转过完整角度(rotate(TAU) 是一整圈),绕其随运动携带的枢轴旋转;任何其他 调用会将其中心沿直线移动;其余的变化(缩放、颜色、新形状)则沿路发生。 自身的 path_arc 或 path_func 会替代该运动。

在任何方法之前调用它会设置动画的 选项: square.animate(run_time=2, rate_func=linear).shift(RIGHT)。它也接受一个编辑, 即一个以方法形式作用于 mobject 的函数: square.animate(lambda mob: mob.shift(RIGHT))。

m.Animate(mobject)
mobject

其方法调用被动画化的 mobject。

源码

manimgx\animation\transform.py

def __init__(self, mobject: M) -> None:
    self._target = mobject.generate_target()
    self._override: Animation | None = None
    self._chaining = False
    self._anim_args: TransformOptions = {}
    self.methods: list[_Call] = []
    super().__init__(mobject, self._target)
    self._chosen: PathFunc | None = self._path_func
    self.keys = (None, self._replay)

到达预备状态

MoveToTarget

代码
import manimgx as m


class MoveToTargetExample(m.Scene):
    def construct(self) -> None:
        circle = m.Circle(radius=2, color=m.BLUE).shift(3 * m.LEFT)
        target = circle.generate_target()
        target.set_fill(m.GREEN, opacity=0.5).scale(0.5).shift(6 * m.RIGHT)
        self.add(circle)
        self.play(m.MoveToTarget(circle))

将一个 mobject 变换为其 target。

先用 generate_target 创建目标,它是该 mobject 的副本,可随意修改;该动画将该 mobject 变换为目标。 没有目标的 mobject 会引发 ValueError。

m.MoveToTarget(mobject, **kwargs)
mobject

要变换的 mobject;其 target 是它所变成的对象。

run_time

动画播放时长,以秒为单位(默认 1)。

lag_ratio

mobject 各部分如何交错:每个部分在其前一个部分开始后,经过其运行时长的该分数比例后开始 (默认 0:全部同时;1:一个接一个)。

rate_func

动画进度如何随时间运行:一个从 [0, 1] 到 [0, 1] 的函数 (默认为 smooth;参见 rate functions)。

reverse_rate_function

是否反向运行动画(默认 False)。

name

动画的名称。

remover

动画结束时 mobject 是否离开场景 (默认 False)。

suspend_mobject_updating

动画期间 mobject 的更新器是否在其下运行(默认 True):它们 持续作用于 mobject,每一帧显示动画应用于其结果。 若为 False,则它们作用于被动画的 mobject 本身。

introducer

动画开始时 mobject 是否加入场景(默认 False); 否则若场景缺少它,play 在其开始时将其带入。

use_override

若某 mobject 的类用另一个动画代替此动画播放,是否如此执行 (默认 True)。

还接受 变换关键字。

源码

manimgx\animation\motion.py

def __init__(self, mobject: M, **kwargs: Unpack[TransformOptions]) -> None:
    if mobject.target is None:
        raise ValueError(
            "MoveToTarget called on a mobject without a target (see"
            " generate_target)"
        )
    super().__init__(mobject, mobject.target, **kwargs)

Restore

代码
import manimgx as m


class RestoreExample(m.Scene):
    def construct(self) -> None:
        square = m.Square(side_length=3, color=m.BLUE, fill_opacity=0.5)
        square.save_state()
        square.scale(0.5).rotate(m.PI / 4).shift(4 * m.LEFT)
        square.set_color(m.YELLOW)
        self.add(square)
        self.play(m.Restore(square, run_time=2))

将一个 mobject 变换回其所保存的状态。

先用 save_state 保存状态;该动画将 mobject 变换为该状态。

m.Restore(mobject, **kwargs)
mobject

要恢复的 mobject。

run_time

动画播放时长,以秒为单位(默认 1)。

lag_ratio

mobject 各部分如何交错:每个部分在其前一个部分开始后,经过其运行时长的该分数比例后开始 (默认 0:全部同时;1:一个接一个)。

rate_func

动画进度如何随时间运行:一个从 [0, 1] 到 [0, 1] 的函数 (默认为 smooth;参见 rate functions)。

reverse_rate_function

是否反向运行动画(默认 False)。

name

动画的名称。

remover

动画结束时 mobject 是否离开场景 (默认 False)。

suspend_mobject_updating

动画期间 mobject 的更新器是否在其下运行(默认 True):它们 持续作用于 mobject,每一帧显示动画应用于其结果。 若为 False,则它们作用于被动画的 mobject 本身。

introducer

动画开始时 mobject 是否加入场景(默认 False); 否则若场景缺少它,play 在其开始时将其带入。

use_override

若某 mobject 的类用另一个动画代替此动画播放,是否如此执行 (默认 True)。

还接受 变换关键字。

源码

manimgx\animation\motion.py

def __init__(self, mobject: Mobject, **kwargs: Unpack[TransformOptions]) -> None:
    super().__init__(mobject.restore, **kwargs)