@thi.ng/hiccup-canvas
Version:
Hiccup shape tree renderer for vanilla Canvas 2D contexts
124 lines (123 loc) • 2.94 kB
JavaScript
import { fromEndPoints } from "@thi.ng/geom-arc/from-endpoints";
import { __endShape } from "./internal/end-shape.js";
const path = (ctx, attribs, segments) => {
ctx.beginPath();
let a = [0, 0];
for (let i = 0, n = segments.length; i < n; i++) {
const s = segments[i];
let b = s[1], c, d;
switch (s[0]) {
// move to
case "m":
b = [a[0] + b[0], a[1] + b[1]];
case "M":
ctx.moveTo(b[0], b[1]);
a = b;
break;
// line to
case "l":
b = [a[0] + b[0], a[1] + b[1]];
case "L":
ctx.lineTo(b[0], b[1]);
a = b;
break;
// horizontal line rel
case "h":
b = [a[0] + b, a[1]];
ctx.lineTo(b[0], b[1]);
a = b;
break;
// horizontal line abs
case "H":
b = [b, a[1]];
ctx.lineTo(b[0], b[1]);
a = b;
break;
// vertical line rel
case "v":
b = [a[0], a[1] + b];
ctx.lineTo(b[0], b[1]);
a = b;
break;
// vertical line abs
case "V":
b = [a[0], b];
ctx.lineTo(b[0], b[1]);
a = b;
break;
// cubic curve rel
case "c":
c = s[2];
d = s[3];
d = [a[0] + d[0], a[1] + d[1]];
ctx.bezierCurveTo(
a[0] + b[0],
a[1] + b[1],
a[0] + c[0],
a[1] + c[1],
d[0],
d[1]
);
a = d;
break;
// cubic curve abs
case "C":
c = s[2];
d = s[3];
ctx.bezierCurveTo(b[0], b[1], c[0], c[1], d[0], d[1]);
a = d;
break;
// quadratic curve rel
case "q":
c = s[2];
c = [a[0] + c[0], a[1] + c[1]];
ctx.quadraticCurveTo(a[0] + b[0], a[1] + b[1], c[0], c[1]);
a = c;
break;
// quadratic curve abs
case "Q":
c = s[2];
ctx.quadraticCurveTo(b[0], b[1], c[0], c[1]);
a = c;
break;
// elliptic arc (SVG compatible)
case "A":
case "a": {
c = s[2];
d = s[6];
s[0] === "a" && (d = [a[0] + d[0], a[1] + d[1]]);
const {
center: [x, y],
start,
end
} = fromEndPoints(a, d, [b, c], s[3], s[4], s[5]);
ctx.ellipse(x, y, b, c, s[3], start, end, !s[5]);
a = d;
break;
}
// circular arc rel
// Note: NOT compatible w/ SVG arc segments
case "r":
c = s[2];
c = [a[0] + c[0], a[1] + c[1]];
ctx.arcTo(a[0] + b[0], a[1] + b[1], c[0], c[1], s[3]);
a = c;
break;
// circular arc abs
// Note: NOT compatible w/ SVG arc segments
case "R":
c = s[2];
ctx.arcTo(b[0], b[1], c[0], c[1], s[3]);
a = c;
break;
// close path
case "z":
case "Z":
ctx.closePath();
}
}
__endShape(ctx, attribs);
};
export {
path
};