squiggle = (x1, y1, x2, y2, lineWidth, value, ctx ) => {
const theta = angleOfInclination(x1, y1, x2, y2);
const [x2a, y2a] = rotatePoint(x2, y2, -theta, x1, y1);
const parts = math.lerp(9, 90, value);
const shift = lineWidth;
const lines = partitionLine(x1, y1, x2a, y2a, parts);
let pts = [[x1, y1], ...lines.map((p) => p[1])];
pts = pts.map(([x, y], i) => [
x + (random.value() * 2 - 1) * lineWidth * math.lerp(0.35, 0.15, value),
y +
(i % 2 === 0 ? -1 : 1) * lineWidth * 0.5 +
(random.value() * 2 - 1) * lineWidth * 0.2
]);
if (random.boolean()) {
pts = pts.map(([x, y]) => {
const yDiff = y - y1;
return [x, y1 + -1 * yDiff];
});
}
pts = pts.map((p) => rotatePoint(p[0], p[1], theta, x1, y1));
const curve = d3
.line()
.curve(d3.curveNatural)
.x((d) => d[0])
.y((d) => d[1]);
ctx.beginPath();
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.strokeStyle = palette.fg(math.lerp(0.4, 1, value));
ctx.lineWidth = 1 + math.lerp(0, 2, value);
curve.context(ctx);
curve(pts);
ctx.stroke();
}