Skip to content
pixi-silk
GitHub repository
Editor kit

Editor tools

Action buttons that orbit the selection, a brush cursor with live resize and pen pressure, a hold-to-show mode ring and a sliding segmented switch.

Updated pixi-silk 1.0.1View as Markdown

Click a shape, then drag it.

Four controls for the tool layer of an editor. ContextHalo is in pixi-silk/ui/halo, BrushCursor in pixi-silk/ui/brush, and ModeSwitcher and SegmentedSwitch in pixi-silk/ui/modes.

Show actions around the selection#

import { ContextHalo } from 'pixi-silk/ui/halo';

const halo = new ContextHalo({
    items: [
        { id: 'copy', label: 'Duplicate', icon: drawMove },
        { id: 'delete', label: 'Delete', icon: drawTrash },
    ],
    bounds: { x: 0, y: 0, width: app.screen.width, height: app.screen.height },
    onSelect: (item) => console.log(item.id, halo.state.target.value),
});

app.stage.addChild(halo);
halo.attach(stage.children[0]);

Round buttons sit on an arc around the target’s box and follow its bounds every frame, so drags, tweens and camera moves need no wiring. Near an edge of bounds the arc turns to the side with room. Attaching another object pops the buttons out at the old one and back in around the new one. Input is off while they pop.

Set state.dragging while the reader drags the target. The halo then follows faster, or folds away with hideWhileDragging: true.

OptionDefaultWhat it does
radius18Radius of each button.
gap10Distance from the target’s box to the buttons.
directionabovePreferred side, as an angle in radians.
boundsnoneThe rectangle the buttons stay inside.
transition'pop''glide' slides the buttons to a new target instead.

An item with disabled: true dims and ignores taps. Its label shows in a pill on hover.

Show the brush under the pointer#

Paint, then hold F and move: sideways is size, up and down is hardness.Open in Studio
import { BrushCursor } from 'pixi-silk/ui/brush';

const brush = new BrushCursor({ size: 24, hardness: 0.8, surface: stage });

app.stage.addChild(brush);
brush.state.size.subscribe((size) => console.log('brush size', size));

The ring is the brush size. A dashed inner ring shows hardness, and a disc grows with pen pressure. Small brushes get a crosshair so the hot spot stays visible. The OS cursor is hidden over surface. The cursor draws the brush and does not paint: read state and paint with your own code.

OptionDefaultWhat it does
size32Brush diameter. Clamped to minSize (1) and maxSize (500).
hardness0.70 is soft, 1 is hard.
resizeKey'KeyF'Hold it and move to resize. The ring stays where the resize began. null turns it off.
rightDragResizetrueA right-button drag resizes too.
bracketKeystrue[ and ] step the size.

state.pressure reads pen pressure from 0 to 1. A mouse reports 0.5 while a button is down.

Switch modes with a held key#

Hold Space over the canvas, or long-press. Tap Space to swap back.Open in Studio
import { ModeSwitcher } from 'pixi-silk/ui/modes';

const modes = new ModeSwitcher({
    modes: [
        { id: 'brush', label: 'BRUSH', icon: drawPointer },
        { id: 'eraser', label: 'ERASER', icon: drawTrash },
    ],
    longPressTarget: app.stage,
    onChange: (mode, previous) => console.log(previous, mode),
});

app.stage.addChild(modes);

Hold key (Space by default) for 160 ms and a ring of modes opens under the pointer, most recently used first. Release over a mode to switch. A quick tap swaps back to the previous mode without showing anything. On touch screens a long-press on longPressTarget opens the same ring.

The key only acts while the pointer is over the canvas and no text field has focus. The ring is a radial menu, styled through the menu option.

Pick one of a few options#

import { SegmentedSwitch } from 'pixi-silk/ui/modes';

const speed = new SegmentedSwitch({
    options: [
        { id: 'slow', label: 'Slow' },
        { id: 'normal', label: 'Normal' },
        { id: 'turbo', label: 'Turbo' },
    ],
    value: 'normal',
});

speed.state.value.subscribe((id) => console.log(id));

A pill of choices with a thumb that slides to the selected one. Tap a segment, or press and slide along the pill: the thumb follows the finger and the choice lands on release. Segments are at least segmentWidth (64) wide and grow to fit their labels or icons.

API reference: ContextHalo, BrushCursor, ModeSwitcher, SegmentedSwitch