Skip to content
pixi-silk
GitHub repository
Shapes & strokes

Lines & paths

Lines and polylines with monotone or Catmull-Rom smoothing, miter, bevel and round joins, Bezier and SVG paths that fill and stroke, and tapered strokes.

Updated pixi-silk 1.0.1View as Markdown

Lines, polylines and paths are the open and free-form shapes of SilkGraphics. Stroke them, or fill a closed path as one shape.

Lower the alpha and look at the corners. Switch the smoothing.
g.polyline([20, 140, 80, 40, 140, 110, 200, 30], { smooth: 'catmull' })
    .stroke({ width: 6, color: 0x0a84ff, alpha: 0.6, cap: 'round' });

That draws a translucent curve through four points. Every pixel of the stroke is shaded once, so the corners have the same alpha as the straight parts instead of darker blobs.

Draw lines and polylines#

g.line(x0, y0, x1, y1).stroke({ width: 2, color: 0xffffff });
g.polyline(points).stroke(...);
g.polyline(points, { closed: true }).stroke(...);

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

OptionDefaultWhat it does
closedfalseConnects the last point back to the first
smoothfalse'monotone' draws a curve that never overshoots the data, for charts. 'catmull' draws a free curve through every point.
step2Sample spacing of the smoothed curve, in local units

Choose a join#

Switch the join and lower the miter limit.
g.polyline(points).stroke({ width: 12, join: 'bevel', color: 0x0a84ff, alpha: 0.6 });
g.rect(0, 0, 80, 60).stroke({ width: 8, join: 'miter', miterLimit: 4 });

join sets how segments meet: 'miter' (the default, as in Canvas and Pixi), 'bevel' or 'round'. A miter longer than miterLimit half widths turns into a bevel. The default limit is 10.

Joins follow Canvas 2D and SVG. A dash that runs through a corner gets the join too. Rects without a radius, and triangles and polygons without a cornerRadius, take the join as well, so a stroked rect() looks like a Canvas one.

Draw Bezier and SVG paths#

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' });

The Canvas-style path API has moveTo, lineTo, quadraticCurveTo, bezierCurveTo and closePath. Curves are flattened into segments that adapt to the curve.

Paths fill as well as stroke. A fill draws the whole path as one shape, so a bolt, a drop or a logo outline takes blur, spread and inner shadows like a circle. Overlapping subpaths follow the even-odd rule: a square inside a square makes a hole.

g.poly([64, 0, 6, 58, 44, 58, 30, 100, 94, 40, 56, 40]).fill({ color: 0xffd60a, blur: 12 });
g.svgPath('M10 80 Q 60 10 110 80 T 210 80').stroke({ width: 3, color: 0x0a84ff });

poly(points) adds a closed polygon. svgPath(d) reads the d attribute of an SVG path. To cut paths out of other shapes, see Shape operations.

A fill checks every edge of its path for each pixel. Keep filled paths to a few hundred points.

Taper a stroke#

Drag the start and end widths.
g.polyline(points).stroke({ width: [2, 22], cap: 'round', gradient: along([0xff9f0a, 0xbf5af2]) });

Pass an array as width. With two values, the width runs from the first to the second along the path length. With one value per point, each value sets the width at its vertex. The taper stays smooth through the joints. along() is a gradient that runs from the first point of the stroke to the last.

Crossings, fold-backs and dash caps#

Pick a case and zoom in.

A translucent stroke stays one shape in the hard cases too.

A path that crosses itself far along its length is shaded once where it overlaps. A path that turns back by 180 degrees, or nearly, goes back over itself with no doubled pixels. A full reversal has no join, as in Canvas. On a curve, square dash caps that overlap the next dash merge into it.

The limit is lines thinner than a pixel. There, crossings of far-apart parts of one path can blend twice.

Long paths#

A path stroke checks the segments of its path for each pixel. Subpaths longer than 32 segments are split into chunks, so a long chart line stays fast. Each chunk also checks the segments of other chunks that come near it, which keeps crossings shaded once. A tapered stroke keeps one capsule per segment.

API reference: SilkGraphics, along, PolylineOptions, LineJoin