# Lines & paths

> Anti-aliased lines and polylines with monotone or Catmull-Rom smoothing, Bezier paths, tapered strokes and translucent joints without double blending.

Source: https://pixi-silk.schmooky.dev/docs/lines-and-paths/

Live demo `polyline` (source):

```ts
import { SilkGraphics } from 'pixi-silk';
import { defineDemo } from './runtime';

export default defineDemo({
    size: [480, 220],
    controls: {
        width: { type: 'range', label: 'width', min: 0.25, max: 16, step: 0.25, value: 6, unit: 'px' },
        smooth: { type: 'select', label: 'smooth', options: ['none', 'monotone', 'catmull'], value: 'none' },
        alpha: { type: 'range', label: 'alpha', min: 0.1, max: 1, step: 0.05, value: 0.6 },
    },
    setup({ stage, params, tick }) {
        const g = new SilkGraphics();

        stage.addChild(g);
        tick((t) => {
            const pts: number[] = [];

            for (let i = 0; i <= 12; i++) pts.push(30 + i * 35, 110 + Math.sin(i * 1.3 + t) * 60 * Math.cos(i * 0.7));
            g.clear();
            // translucent on purpose: every pixel is shaded once, so joints never double-blend
            g.polyline(pts, { smooth: params.smooth === 'none' ? undefined : (params.smooth as 'monotone') }).stroke({
                width: params.width,
                color: 0x0a84ff,
                alpha: params.alpha,
                cap: 'round',
            });
            for (let i = 0; i < pts.length; i += 2) g.circle(pts[i], pts[i + 1], 3).fill(0xffffff);
        });
    },
});
```

## Lines and polylines

```ts nocheck
g.line(x0, y0, x1, y1).stroke({ width: 2, color: 0xffffff });
g.polyline([x0, y0, x1, y1, x2, y2]).stroke({ width: 3, color: 0x0a84ff, cap: 'round' });
g.polyline(points, { closed: true }).stroke(...);            // closed loop
g.polyline(points, { smooth: 'monotone' }).stroke(...);      // charts: never overshoots the data
g.polyline(points, { smooth: 'catmull' }).stroke(...);       // free curves through every point
```

Points can be a flat array `[x0, y0, x1, y1, ...]`, a typed array, or an array of `{ x, y }`.

Each segment is its own instance. For every pixel, only the nearest segment shades it. So a
translucent polyline has uniform alpha at its joints instead of darker blobs. For the same reason,
joints are always round. Round is the only join that is continuous in distance.

## Paths

The canvas-style path API works for strokes:

```ts
g.moveTo(10, 80)
    .quadraticCurveTo(60, 10, 110, 80)
    .bezierCurveTo(140, 120, 180, 20, 220, 60)
    .lineTo(260, 60)
    .stroke({ width: 3, color: 0xff9f0a, cap: 'round' });
```

Silk flattens curves adaptively into segments. Free-form paths are stroke-only. For filled
regions, use closed primitives or [`area()`](/docs/charts/).

## Tapered strokes

Pass an array as `width`. With `[start, end]`, Silk interpolates the width along the path length.
With one value per point, each value sets the width at its vertex. Each segment becomes an uneven
capsule, so the taper is smooth through joints.

Live demo `taper` (source):

```ts
import { along, SilkGraphics } from 'pixi-silk';
import { defineDemo } from './runtime';

const INK = along([0xff9f0a, 0xff375f, 0xbf5af2]);

export default defineDemo({
    size: [480, 220],
    controls: {
        start: { type: 'range', label: 'start width', min: 0, max: 30, step: 0.5, value: 2 },
        end: { type: 'range', label: 'end width', min: 0, max: 30, step: 0.5, value: 22 },
    },
    setup({ stage, params, tick }) {
        const g = new SilkGraphics();

        stage.addChild(g);
        tick((t) => {
            const pts: number[] = [];

            for (let i = 0; i <= 40; i++) {
                const u = i / 40;

                pts.push(40 + u * 400, 110 + Math.sin(u * 7 + t) * 50 * (1 - u * 0.5));
            }
            g.clear();
            // `width: [start, end]` tapers along the path; an array per point also works
            g.polyline(pts).stroke({ width: [params.start, params.end], cap: 'round', gradient: INK });
        });
    },
});
```

```ts
g.polyline(points).stroke({ width: [2, 22], cap: 'round', gradient: along([0xff9f0a, 0xbf5af2]) });
```

`along()` is a gradient that follows the stroke from its first point to its last.

## Hairlines

Strokes thinner than one device pixel stay one pixel wide and fade in proportion. They do not break
up into dots. See [Fills & strokes](/docs/fills-and-strokes/#hairlines).
