# 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.

Source: https://pixi-silk.schmooky.dev/docs/arcs-and-rings/

Live demo `rings` (source):

```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

```ts nocheck
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.

```ts
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.

```ts
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

```ts
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.

```ts
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;
}
```
