Recreating this GIF.
Last active
May 25, 2017 01:47
-
-
Save veltman/73f1ffbd388f0fad1e559b47a8a4a9ba to your computer and use it in GitHub Desktop.
Unfolding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<style> | |
body { | |
background-color: #ccc; | |
} | |
path { | |
stroke: black; | |
stroke-width: 3px; | |
stroke-linecap: round; | |
stroke-linejoin: round; | |
fill: #fff; | |
} | |
path:last-of-type { | |
stroke-width: 1px; | |
fill: none; | |
} | |
</style> | |
</head> | |
<body> | |
<svg width="960" height="500"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
var width = 960, | |
height = 500, | |
sides = d3.scaleLinear().range([1, 12]), | |
svg = d3.select("svg").append("g").attr("transform", "translate(" + width / 2 + ")"), | |
line = d => "M" + d.join("L") + "Z", | |
path = svg.append("path"), | |
inner = svg.append("path"); | |
d3.timer(function(t) { | |
var out = (t = t % 15000 / 15000) < 0.5, | |
progress = sides(d3.easeSinInOut(Math.min(t, 1 - t) * 2)), | |
start = poly(out ? Math.floor(progress) : Math.ceil(progress), out), | |
end = poly(out ? Math.ceil(progress) : Math.floor(progress), !out), | |
remainder = progress % 1; | |
if (!remainder) { | |
end = start; | |
} | |
inner.attr("d", d3.range(3, progress).map(i => line(poly(i))).join(" ")); | |
path.attr("d", line(d3.interpolateArray(start, end)(out ? remainder : 1 - remainder))); | |
}); | |
function poly(s, addPoint) { | |
var r = 120 / (2 * Math.sin(Math.PI / s)), | |
points = s === 1 | |
? [[0, 0]] | |
: d3 | |
.range(s) | |
.map(i => [ | |
r * Math.cos(2 * Math.PI * i / s - Math.PI / 2 - (s % 2 ? 0 : Math.PI / s)), | |
r * Math.sin(2 * Math.PI * i / s - Math.PI / 2 - (s % 2 ? 0 : Math.PI / s)) | |
]), | |
bottom = points[s > 2 ? ~~(s / 2) + 1 : 0][1]; | |
points.forEach(d => d[1] += height - bottom - 25); | |
if (addPoint) { | |
if (s % 2) { | |
points.unshift(points[0]); | |
} else { | |
points.splice(1, 0, [0, points[0][1]]); | |
points.push(points.shift()); | |
} | |
} | |
return points; | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment