Skip to content
pixi-silk
GitHub repository
Editor kit

Dials and timeline

A jog wheel with fine control and inertia, scrub fields you drag sideways, and a compact animation timeline with keys, a loop range and zoom for PixiJS.

Updated pixi-silk 1.0.1View as Markdown

Turn the dials and scrub the fields. The left dial also drives the Angle field.Open in Studio

Controls for numbers and time. JogDial and Scrubber are in pixi-silk/ui/dial, and MiniTimeline is in pixi-silk/ui/timeline. For a rolling number readout, see the odometer on Interaction and motion.

Turn a value with a jog dial#

import { JogDial } from 'pixi-silk/ui/dial';

const camera = { zoom: 1 };
const undo: number[] = [];
const zoom = new JogDial({
    radius: 64,
    turn: 2,
    step: 0.1,
    min: 0.1,
    max: 8,
    onChange: (v) => (camera.zoom = v),
    onCommit: (v) => undo.push(v),
});

Press anywhere on the dial and drag around its centre. The value follows the angle and keeps adding up over full turns, so there is no seam at the top. Past the ring the dial turns slower the further out the pointer is, which gives fine control without letting go.

A fast release keeps the dial spinning until friction stops it. With min and max the ring becomes a gauge of the range, and past a limit the value stretches and springs back. A tap on the right half steps up, on the left half down. onChange fires on every snapped change and onCommit once the dial rests.

OptionDefaultWhat it does
turnthe range, else 1Value change for one full turn near the ring.
step0Snap step. 0 turns snapping off.
fine1How fast precision grows with distance: the speed is (radius / distance) ** fine. 0 turns it off.
rubber0.12How far the value stretches past a limit, as a fraction of a turn.
inertiatrueKeep spinning after a flick.
friction3.5How quickly a flick slows down, about 1 / seconds.

Drag a number field#

import { Scrubber } from 'pixi-silk/ui/dial';

const size = new Scrubber({ label: 'Size', value: 24, step: 1, min: 1, max: 200, perPixel: 0.5 });

Drag the field sideways to change its value. Shift scrubs at a tenth of the speed (fineFactor), and Ctrl or Cmd snaps to the step. A tap on either end steps down or up. With min and max the field fills like a slider. perPixel defaults to a quarter of the step.

Both controls keep their value in state.value, a signal you can also write to move them.

Scrub an animation timeline#

Scrub, drag keys, box-select, move the loop handles. Tap the dial to pause.Open in Studio
import { MiniTimeline } from 'pixi-silk/ui/timeline';

const timeline = new MiniTimeline({
    duration: 120,
    fps: 30,
    loop: [24, 96],
    keys: [
        { id: 'jump', time: 30 },
        { id: 'land', time: 44 },
    ],
    onKeysChange: (keys) => localStorage.setItem('keys', JSON.stringify(keys)),
});

timeline.state.time.subscribe((frame) => console.log('frame', frame));
timeline.state.playing.set(true);

Times are in frames. Scrub the ruler to move the playhead, which snaps to frames and stretches past either end. Drag a key to move it, Shift + click to add keys to the selection, or drag on empty track for a selection box. Selected keys move together and stop at the ends of the track. Drag the green handles on the ruler to set the loop range, and playback wraps inside it.

The wheel zooms around the pointer and Shift + wheel pans. Pixi listens to the wheel passively, so the page scrolls too unless the canvas fills it. Without a wheel, a double tap on the ruler zooms in and another zooms back out. zoomBy(), panBy() and showAll() do the same from code.

StateWhat it holds
timePlayhead time in frames. Writing it moves the playhead.
playingWriting it starts or stops playback.
selectionIds of the selected keys.
rangeLoop range in frames, or null for the whole track.
viewThe visible window in frames.
OptionDefaultWhat it does
duration120Length in frames.
fps30Playback speed.
snap1Keys and the playhead snap to multiples of this many frames. 0 turns it off.
minSpan8Fewest frames the view zooms in to.
fontSize9Size of the frame numbers on the ruler. fontFamily and textStyle set the rest.
labelBitmapTextBuilds the frame numbers. Pass silkLabel() from pixi-silk/text for SDF text.

The timeline holds keys and a playhead, not animation curves. Use state.time to drive your own tweens or a Spine track.

API reference: JogDial, Scrubber, MiniTimeline