Skip to content
GitHub repository
Drawing

Arcs, sectors & rings

Arcs with round, butt or square caps, pie and donut sectors with rounded corners, and activity rings whose conic gradients follow the arc.

Updated pixi-silk 0.1.0

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

const RINGS = [
    { r: 78, colors: [0xfa114f, 0xff5e8a] },
    { r: 58, colors: [0x92e82a, 0xd4ff5a] },
    { r: 38, colors: [0x1ee0ff, 0x7df9ff] },
].map((ring) => ({ ...ring, gradient: conic(ring.colors) }));

export default defineDemo({
    size: [260, 200],
    controls: {
        progress: { type: 'range', label: 'progress', min: 0, max: 1.6, step: 0.01, value: 0.8 },
        cap: { type: 'select', label: 'cap', options: ['round', 'butt', 'square'], value: 'round' },
    },
    setup({ stage, params, tick }) {
        const g = new SilkGraphics();

        stage.addChild(g);
        tick((t) => {
            g.clear();
            RINGS.forEach((ring, i) => {
                const p = Math.max(0.001, params.progress * (1 - i * 0.18) + Math.sin(t + i) * 0.02);

                g.circle(130, 100, ring.r).stroke({ width: 16, color: ring.colors[0], alpha: 0.18 });
                // the conic gradient spans whatever arc it is drawn on
                g.arcSweep(130, 100, ring.r, -Math.PI / 2, Math.PI * 2 * p).stroke({
                    width: 16,
                    cap: params.cap as 'round',
                    gradient: ring.gradient,
                });
            });
        });
    },
});

Arcs#

g.arc(cx, cy, radius, startAngle, endAngle, anticlockwise?);   // canvas semantics
g.arcSweep(cx, cy, radius, startAngle, sweep);                 // signed sweep, clockwise on screen

Arcs are open curves, so you stroke them. cap sets the shape of the ends. The default is 'butt', as in Pixi. Angles are in radians with y pointing down, so -Math.PI / 2 is 12 o’clock and positive sweeps turn clockwise. Each arc starts its own subpath. Unlike Graphics.arc, it does not connect to the previous point.

g.arcSweep(100, 100, 60, -Math.PI / 2, Math.PI * 2 * progress)
    .stroke({ width: 14, cap: 'round', color: 0x30d158 });

A sweep of 2π or more draws a full ring. The primitive is one exact distance field, so a ring is as cheap as a circle.

Gradients on arcs#

A conic() gradient on an arc spans that arc. Its start and sweep default to the arc’s own. So the ramp always runs from the start cap to the end cap, however long the arc is.

const RING = conic([0xfa114f, 0xff5e8a]);

g.arcSweep(100, 100, 60, -Math.PI / 2, sweep).stroke({ width: 16, cap: 'round', gradient: RING });

Sectors and donut segments#

g.sector(cx, cy, radius, startAngle, endAngle, innerRadius = 0, cornerRadius = 0);

innerRadius turns a pie slice into a donut segment. cornerRadius rounds all of its corners. Sectors are closed shapes, so you can fill them, stroke them, or both. Gauges, pie charts and radial menus are a loop of sectors.

const slices = [0.4, 0.25, 0.2, 0.15];
const COLORS = [0x0a84ff, 0x30d158, 0xffd60a, 0xff375f];
let a = -Math.PI / 2;

for (const [i, share] of slices.entries()) {
    const sweep = share * Math.PI * 2;

    g.sector(120, 120, 90, a + 0.02, a + sweep - 0.02, 50, 6).fill(COLORS[i]);
    a += sweep;
}

API reference: SilkGraphics, conic