Skip to content

Instantly share code, notes, and snippets.

@kristw
Last active April 28, 2017 18:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kristw/033d294f3dd8896dbc5b7dce14035e92 to your computer and use it in GitHub Desktop.
Save kristw/033d294f3dd8896dbc5b7dce14035e92 to your computer and use it in GitHub Desktop.
Trembling triangle horse
license: mit
<!DOCTYPE html>
<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 = 60000,
triangle = [[1,249],[63,123],[59,94],[49,109],[42,115],[33,114],[27,106],[26,93],[30,85],[36,68],[34,57],[34,52],[39,42],[40,36],[38,27],[38,13],[46,25],[46,29],[55,26],[59,27],[60,16],[66,18],[70,26],[71,33],[79,37],[89,37],[89,45],[97,45],[94,53],[95,57],[98,55],[125,0],[184,117],[194,115],[206,119],[216,126],[224,137],[227,147],[228,158],[234,167],[243,167],[250,161],[254,155],[255,159],[252,165],[246,170],[249,171],[254,169],[250,175],[255,172],[253,177],[259,173],[257,180],[251,187],[245,187],[234,187],[220,191],[249,248],[182,249],[175,260],[171,271],[170,279],[171,289],[170,293],[162,295],[156,294],[155,290],[165,264],[165,260],[165,249],[148,249],[147,256],[147,262],[152,265],[157,264],[158,275],[154,283],[147,287],[143,287],[140,284],[137,264],[132,257],[136,249],[119,249],[119,255],[124,260],[129,261],[126,264],[127,269],[131,268],[136,269],[138,285],[137,288],[134,291],[131,293],[126,291],[123,288],[120,284],[120,279],[114,283],[109,284],[104,284],[101,282],[99,279],[99,274],[105,266],[111,263],[115,263],[117,262],[110,249],[97,249],[97,256],[98,260],[104,265],[107,264],[97,276],[81,261],[80,249]],
line = d3.line().context(context),
pixelScale = d3.scaleLinear()
.range([2, 8]),
depthScale = d3.scaleLinear()
.rangeRound([3, 7]),
offsetter;
context.globalAlpha = 0.1;
context.translate(50, 50);
d3.timer(function(t){
t = Math.min(t % interval / interval, 1 - t % interval / interval) * 2;
offsetter = d3.randomNormal(0, pixelScale(t));
context.clearRect(-50, -50, 960 + 100, 500 + 100);
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 = [
a[0] + (b[0] - a[0]) * 0.5 + offsetter(),
a[1] + (b[1] - a[1]) * 0.5 + offsetter()
];
if (depth === 1) {
return [midpoint];
}
return [...getBetween(a, midpoint, depth - 1), midpoint, ...getBetween(midpoint, b, depth - 1)];
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment