Similar to this shaky triangle but with a different offsetting technique.
forked from veltman's block: Trembling triangle #2
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
let context = document.querySelector("canvas").getContext("2d"),
interval = 45000,
triangle = [[480, 50], [680, 450], [280, 450]],
line = d3.line().context(context),
pixelScale = d3.scaleLinear()
.range([2, 8]),
depthScale = d3.scaleLinear()
.rangeRound([3, 7]),
getDistance = d3.randomNormal(0.5, 0.15),
getOffset;
context.globalAlpha = 0.1;
d3.timer(function(t){
t = Math.min(t % interval / interval, 1 - t % interval / interval) * 2;
getOffset = d3.randomNormal(0, pixelScale(t));
context.clearRect(0, 0, 960, 500);
context.fillStyle = d3.interpolateWarm(t / 2);
for (let i = 0; i < 10; i++) {
context.beginPath();
line(tremble(triangle, depthScale(t)));
context.closePath();
context.fill();
}
});
function tremble(shape, depth) {
return shape.reduce((newPoints, val, i) => {
return [...newPoints, val, ...getBetween(val, shape[i + 1] || shape[0], depth)];
}, []);
}
function getBetween(a, b, depth) {
const midpoint = getMidpoint(a, b);
if (depth === 1) {
return [midpoint];
}
return [...getBetween(a, midpoint, depth - 1), midpoint, ...getBetween(midpoint, b, depth - 1)];
}
function getMidpoint(a, b) {
let along = pointAlong(a, b, getDistance()),
distance = distanceBetween(a, b),
offset = getOffset();
return [
along[0] + offset * (a[1] - b[1]) / distance,
along[1] - offset * (a[0] - b[0]) / distance
];
}
</script>
https://d3js.org/d3.v4.min.js