Skip to content
GitHub repository
Drawing

Dashes & dots

Dash patterns computed in the shader, with caps on every dash, dots from zero-length dashes, closed outlines without a seam, and marching ants.

Updated pixi-silk 0.1.0

Source src/demos/dashes.demo.ts
import { SilkGraphics, type StrokeStyle } from 'pixi-silk';
import { defineDemo } from './runtime';

export default defineDemo({
    size: [480, 220],
    controls: {
        dash: { type: 'range', label: 'dash', min: 0, max: 30, step: 1, value: 10 },
        gap: { type: 'range', label: 'gap', min: 2, max: 30, step: 1, value: 8 },
        cap: { type: 'select', label: 'cap', options: ['butt', 'round', 'square'], value: 'round' },
        march: { type: 'toggle', label: 'animate', value: true },
    },
    setup({ stage, params, tick }) {
        const g = new SilkGraphics();

        stage.addChild(g);
        tick((t) => {
            const style: StrokeStyle = {
                width: 6,
                cap: params.cap as StrokeStyle['cap'],
                dash: [params.dash, params.gap],
                dashOffset: params.march ? t * 24 : 0,
            };

            g.clear();
            g.circle(90, 110, 70).stroke({ ...style, color: 0x64d2ff }); // on closed outlines the pattern tiles without a seam
            g.line(200, 40, 440, 40).stroke({ ...style, color: 0xffd60a });
            g.polyline([200, 180, 260, 90, 320, 160, 380, 80, 440, 150], { smooth: 'catmull' }).stroke({
                ...style,
                color: 0xff375f,
            });
            g.line(200, 110, 440, 110).stroke({ width: 8, cap: 'round', dash: [0, 16], color: 0x30d158 }); // 0-length dashes = dots
        });
    },
});

You can dash any stroke. The fragment shader computes the pattern along the path length. This costs nothing extra on the CPU, and every dash gets its own caps.

g.circle(90, 90, 60).stroke({ width: 4, color: 0x64d2ff, dash: [10, 6] });        // [dash, gap]
g.line(0, 0, 300, 0).stroke({ width: 4, color: 0xffd60a, dash: 8 });               // equal dash and gap
g.line(0, 20, 300, 20).stroke({ width: 8, cap: 'round', dash: [0, 16], color: 0x30d158 }); // dots

Dots#

A dash of length 0 draws a dot with cap: 'round' and a square with cap: 'square'. The pattern repeats every dash + gap units, so dash: [0, 16] places a dot every 16 units.

Marching ants and spinners#

Animate dashOffset to move the pattern along the path:

app.ticker.add(() => {
    g.clear().circle(80, 80, 56).stroke({ width: 3, color: 0xffffff, dash: [6, 6], dashOffset: t * 30 });
});

Closed outlines#

On closed shapes (circles, ellipses, closed polylines), Silk stretches the pattern slightly so it tiles the perimeter exactly. This avoids a short dash where the path starts. Set dashFit: false to keep the exact lengths.

API reference: StrokeStyle