Animation
This content is for v0.4. Switch to the latest version for up-to-date documentation.
Almost every value you can change over time is written the same way, as constant or keyframed. This page covers that form, the interpolation curves, and the one thing that trips people up: which clock a keyframe’s time is measured on.
Constant or keyframes
Section titled “Constant or keyframes”An animatable value is an object with a mode:
{ "mode": "constant", "value": 0.5 }{ "mode": "keyframes", "keyframes": [ { "time": 0, "value": 0, "interpolation": { "type": "linear" } }, { "time": 60000, "value": 1, "interpolation": { "type": "hold" } } ]}- Keyframes must be in strictly ascending
timeorder. The engine refuses a sequence out of order. - Before the first keyframe the value is the first keyframe’s; after the last, the last one’s.
- A keyframe’s
interpolationsays how the value moves from it to the next keyframe. The last keyframe’s interpolation is never used, soholdis a natural choice there.
The value type depends on the field: a number for opacity, { "x", "y" } for a position or scale, a paint, an effect value ({ "type": "float", "value": 0.4 }) for an effect parameter, a string for a layout text. The schema lists them as Animated_float, Animated_Vec2, Animated_EffectValue and so on (reference).
Interpolation
Section titled “Interpolation”Interpolation has three types:
| Type | Moves to the next value |
|---|---|
hold |
Not at all: the value jumps when the next keyframe arrives. |
linear |
At a constant rate. |
cubic_bezier |
Along a CSS cubic-bezier(x1, y1, x2, y2) timing curve. x1 and x2 are in 0..1; y1 and y2 may overshoot. |
alpha2/project has the CSS named curves as values: EASING_PRESETS.ease is cubic_bezier(0.25, 0.1, 0.25, 1), and there are easeIn, easeOut, easeInOut and linear, plus cubicBezier(x1, y1, x2, y2) and HOLD.
Values interpolate numerically: a rotation from 0 to 720 degrees turns twice. Normalize your keyframes if you want the shortest path.
Easing, used by transitions, is the same without hold.
Some values never interpolate:
enumandbooleffect parameters only hold.- Strings (layout text) only hold.
- An interpolated effect parameter that overshoots its range is clamped to it. A keyframe value you author outside the range is an error.
A position (AnimatedPoint) can also travel along a curve: give its keyframes an out_tangent and the next one an in_tangent, and the point follows the cubic Bezier through them. The interpolation then sets how fast it travels along that path.
Whose time?
Section titled “Whose time?”A keyframe’s time is in ticks, but measured from different starting points depending on who owns the value:
| Owner | Keyed in | Starts at zero when |
|---|---|---|
A clip’s visual, its masks, a timeline transition’s parameters |
Timeline time | The project starts. |
| A composition node’s settings (effect parameters, transforms) | Composition time | The clip starts (by default; see ClipComposition). |
| Shapes and layout generators | Picture time | The source time the clip selects is zero. |
The reasoning: a clip’s visual places the clip on the timeline, so it is keyed in timeline time. A composition moves with the clip that shows it. A generated picture is a source, trimmed and placed by its clips just as a video file is.
This project uses all three:
{ "schema_version": 1, "id": "animation", "name": "Animation time bases", "settings": { "width": 1280, "height": 720, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000 }, "sources": [ { "id": "boathouse", "kind": "image", "locator": "asset://boathouse" }, { "id": "dot", "kind": "generated", "generator": { "type": "shapes", "items": [ { "type": "ellipse", "center": { "mode": "keyframes", "keyframes": [ { "time": 0, "value": { "x": 0.15, "y": 0.8 }, "interpolation": { "type": "cubic_bezier", "x1": 0.25, "y1": 0.1, "x2": 0.25, "y2": 1 } }, { "time": 240000, "value": { "x": 0.85, "y": 0.8 }, "interpolation": { "type": "hold" } } ] }, "size": { "mode": "constant", "value": { "x": 0.06, "y": 0.1067 } } }, { "type": "fill", "paint": { "mode": "constant", "value": { "type": "solid", "color": { "red": 1, "green": 0.7, "blue": 0.1, "alpha": 1 } } } } ] } } ], "compositions": [ { "id": "focus", "nodes": [ { "id": "picture", "op": { "type": "clip" } }, { "id": "blur", "op": { "type": "effect", "input": "picture", "effect": { "id": "alpha2.effect.gaussian-blur", "version": 1, "params": { "radius": { "mode": "keyframes", "keyframes": [ { "time": 0, "value": { "type": "float", "value": 0.03 }, "interpolation": { "type": "linear" } }, { "time": 120000, "value": { "type": "float", "value": 0 }, "interpolation": { "type": "hold" } } ] } } } } } ], "output": "blur" } ], "timeline": { "tracks": [ { "id": "picture", "name": "Picture", "kind": "video", "clips": [ { "id": "photo", "source_id": "boathouse", "timeline_range": { "start": 0, "end": 480000 }, "source_range": { "start": 0, "end": 480000 }, "composition": { "id": "focus" }, "visual": { "scale": { "mode": "keyframes", "keyframes": [ { "time": 0, "value": { "x": 1, "y": 1 }, "interpolation": { "type": "linear" } }, { "time": 480000, "value": { "x": 1.15, "y": 1.15 }, "interpolation": { "type": "hold" } } ] }, "opacity": { "mode": "keyframes", "keyframes": [ { "time": 0, "value": 0, "interpolation": { "type": "cubic_bezier", "x1": 0.25, "y1": 0.1, "x2": 0.25, "y2": 1 } }, { "time": 60000, "value": 1, "interpolation": { "type": "hold" } } ] } } } ] }, { "id": "overlay", "name": "Overlay", "kind": "video", "clips": [ { "id": "dot-clip", "source_id": "dot", "timeline_range": { "start": 120000, "end": 420000 }, "source_range": { "start": 0, "end": 300000 } } ] } ] }}- The photo’s
visual.opacityandvisual.scaleare keyed in timeline time: the fade-in runs from 0 to 0.5 s of the project and the slow zoom over the whole four seconds. - The blur’s
radiusin thefocuscomposition is keyed in composition time: it clears over the clip’s first second. - The dot’s
centeris keyed in picture time of thedotsource, from 0 to 2 s. The clip puts that picture on the timeline at 1 s, so the dot starts moving at 1 s and stops at 3 s.
Shapes in picture time
Section titled “Shapes in picture time”The shapes preset keys an ellipse’s centre in picture time, so it moves across the three seconds of its clip:
