Timeline
Key control values over time, then play them back:
const timeline = gui.timeline({ duration: 8, loop: true });
timeline.play(); // its own clock…
timeline.update(dt); // …or your frame loop's
timeline.sample(t); // …or your own time
timeline.key('Anim/speed', 2, 0.5); // keys from code too (canonical values)
timeline.unkey('Anim/speed', 2);
timeline.pause(); timeline.seek(4); timeline.record(true);
timeline.valueAt('Anim/speed', 1.5); // what a track gives at a time
gui.timeline({ name: 'intro', duration: 3, autoplay: true }); // more than one, by name
- Keying: with a timeline, each number, vector, colour and boolean row has a ◆. Click it to key the value at the playhead. It's filled on a key, and orange once you change the value (click to key the change). Right-click a row for the same. Record keys every change you make as it plays or as you scrub.
- The window (the timeline button in the header; it opens docked along the bottom):
- The transport: to the start, play (Space), record, the time and length, and loop.
- The ruler: drag to scrub, double-click to see it all, scroll to zoom. Over the tracks a scroll scrolls them and Ctrl/⌘ + scroll (or a pinch) zooms; Shift + scroll, the middle button or two fingers pan; + and − zoom and 0 (or fit in the bar, while zoomed) shows it all (see gestures).
- Tracks, one per keyed control, with a faint preview of the value (a colour strip for colours). Click a key to go to it, drag keys to move them (snapped to frames; Shift for tenths of a second), drag on empty space to box-select, Delete, ⌘/Ctrl+C and V to copy and paste at the playhead, double-click a track to key it there. The selected keys' interpolation is in the bar.
- A track's curve opens in the curve editor (a component at a time for a vector).
- Interpolation: smooth (no overshoot), linear or step per key; colours blend in OKLab, their alpha on a curve of its own; booleans step.
- What it sets isn't saved as your values and isn't undoable: it's a
'timeline'change. Key edits are undoable, and a dragged key (or a recorded drag) is one step. - Saved with the values (locally, in
save(), and in a linked file), and production builds play it back: the noop build'sgui.timeline()reads the keys from the values file and sets the same properties. Numbers and vectors follow the same curves; colours too, written in the value's own form (any CSS string, a number,{ r, g, b, a },[r, g, b, a], linear or not, bytes or not, as saved with the track); other values step through their keys' values. Its player is a chunk of its own (about 1.5 KB gzip), loaded as values with timelines in them load, or atgui.timeline(): an app with no timeline loads none of it. A seek made before it's in lands when it is;await gui.ready()waits for it.