跳轉到

快速開始

一個點在視野中移動,同一段動畫寫成三種格式。

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

點用三次 ease-out 從 (1, 1) 移到 (9, 9)。

Animation(scene, motion=None, *, registry=..., interactions=None, accessibility=None)
sceneSceneBase

場景:節點、疊層與相機。2D 與 3D 場景都可以。

motionMotion | None預設值: None

動作樹。None 表示靜止的動畫。

interactionsInteractionSpec | None預設值: None

綁定到節點編號的宣告式互動(參見文字與無障礙)。

accessibilityAccessibilityInfo | None預設值: None

標題、說明文字、語言與減少動態的處理方式。

把不可變場景與動作接在一起的門面。frames() 會逐張產生快照,sample(t) 回傳某個時間點的場景,save() 依目的檔的副檔名選擇匯出器。

Animation.save(target, *, renderer=None, **options) → Any
targetstr | PathLike | Destination

檔案路徑、串流或其他輸出目標。路徑的副檔名決定格式:.svg、.gif 或 .html。

rendererstr | None預設值: None

指定繪圖端: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,
)
idstr

穩定的編號。動作、互動與場景轉場都靠它找到節點。

positionVec2預設值: Vec2(x=0.0, y=0.0)

點的位置,使用世界座標。

sizefloat預設值: 4.0

標記大小,單位同輸出。

colorColor | str預設值: ...

填色:Color,或像 "#e4572e" 這樣的字串。

opacityfloat預設值: 1.0

從 0(隱藏)到 1(不透明)。

semanticsSemantics | None預設值: None

給輔助科技使用的角色、標籤與閱讀順序。

一個圓形的 2D 標記,有穩定編號、位置、大小、顏色與透明度。這些屬性都能透過 node.animate 製作動畫。

Bounds2D(min, max)
minVec2

左下角。

maxVec2

右上角。

與座標軸平行的矩形,用於相機視野、裁切、版面與範圍。

Vec2(x, y)
xfloat

水平分量。

yfloat

垂直分量。

不可變的二維向量,用來表示位置、方向與大小。

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,而且不會留下半個檔案(參見輸出格式)。

留言