快速开始
一个点在视野中移动,同一段动画写成三种格式。
from kinetickit import Animation, Bounds2D, Point2D, Scene2D, Vec2, ease
dot = Point2D(id="dot", position=Vec2(1, 1), size=8, color="#e4572e")
scene = Scene2D(dot)
scene = scene.bind({scene.camera.ref("view"): Bounds2D(Vec2(0, 0), Vec2(10, 10))})
motion = dot.animate.position.to(Vec2(9, 9), duration=1.5, easing=ease.out_cubic)
animation = Animation(scene, motion)
animation.save("dot.svg", width=400, height=400) # 原生动态 SVG
animation.save("dot.gif", width=400, height=400, fps=30) # 需要 kinetickit[raster]
animation.save("dot.html", width=400, height=440) # 需要 kinetickit[interactive]
点用三次 ease-out 从 (1, 1) 移到 (9, 9)。
Animation(scene, motion=None, *, registry=..., interactions=None, accessibility=None)
场景:节点、叠层与相机。2D 与 3D 场景都可以。
动作树。None 表示静止的动画。
绑定到节点编号的声明式交互(参见文本与无障碍)。
标题、说明文本、语言与减少动态的处理方式。
把不可变场景与动作接在一起的门面。frames() 会逐张产生快照,sample(t) 返回某个时间点的场景,save() 依目的档的扩展名选择导出器。
Animation.save(target, *, renderer=None, **options) → Any
文件路径、串流或其他输出目标。路径的扩展名决定格式:.svg、.gif 或 .html。
指定绘图端:vector、raster 或 interactive。None 则依格式决定。
所选输出的选项,例如 width、height、fps 或 title(参见输出格式)。
写出动画并返回 ExportManifest。写档是原子操作:导出失败时不会留下半个文件。
Scene2D(*nodes, overlay=(), camera=None)
由 2D 节点与一个相机组成的不可变集合。bind() 会返回设好相机视野的新场景,不会修改原来的场景。
Point2D(
*,
id,
opacity=1.0,
z=0.0,
visible=True,
semantics=None,
position=Vec2(x=0.0, y=0.0),
size=4.0,
symbol='circle',
color=...,
stroke=None,
stroke_width=1.0,
)
稳定的编号。动作、交互与场景转场都靠它找到节点。
点的位置,使用世界坐标。
标记大小,单位同输出。
填色:Color,或像 "#e4572e" 这样的字符串。
从 0(隐藏)到 1(不透明)。
给辅助科技使用的角色、标签与阅读顺序。
一个圆形的 2D 标记,有稳定编号、位置、大小、颜色与透明度。这些属性都能通过 node.animate 制作动画。
与坐标轴平行的矩形,用于相机视野、裁切、版面与范围。
不可变的二维矢量,用来表示位置、方向与大小。
ease.linear(u)
ease.in_quad(u), ease.out_quad(u), ease.in_out_quad(u)
ease.in_cubic(u), ease.out_cubic(u), ease.in_out_cubic(u)
ease.in_quart(u), ease.in_quint(u), ease.in_sine(u), ease.in_expo(u)
ease.cubic_bezier(x1, y1, x2, y2)
缓动函数的命名空间。时间与缓动列出所有函数。
读出某个时间的场景
场景加上时间,一定得到相同的状态,所以不必播放动画,就能问任何一个时刻的样子。
print(animation.duration) # 1.5
print(animation.sample(0.0).get("dot").position) # Vec2(x=1.0, y=1.0)
print(animation.sample(0.75).get("dot").position) # Vec2(x=8.0, y=8.0)
print(animation.sample(1.5).get("dot").position) # Vec2(x=9.0, y=9.0)
0.75 秒时进度是 0.5,三次 ease-out 走完 \(1 - (1 - 0.5)^3 = 0.875\),所以点在 \(1 + 8 \times 0.875 = 8\)。
组合动作
动作是一个值。用 then、with_、delay、repeat、yoyo、reverse 与 trim 把动作组合起来,并用 mark 替某个时刻命名。
from kinetickit import Animation, Bounds2D, Point2D, Scene2D, Vec2
a = Point2D(id="a", position=Vec2(0, 0), size=8)
b = Point2D(id="b", position=Vec2(0, 5), size=8, opacity=0.0)
c = Point2D(id="c", position=Vec2(5, 5), size=4)
scene = Scene2D(a, b, c)
scene = scene.bind({scene.camera.ref("view"): Bounds2D(Vec2(-1, -1), Vec2(11, 11))})
motion = (
a.animate.position.to(Vec2(5, 5), duration=1.0)
.then(b.animate.opacity.to(1.0, duration=0.5).with_(c.animate.size.to(9, duration=0.5)))
.mark("settled")
)
print(Animation(scene, motion).duration) # 1.5
GIF 与 HTML 那两行需要对应的额外安装项。能力检查会在打开目的档之前运行,所以不支持的组合会抛出 CapabilityError,而且不会留下半个文件(参见输出格式)。