|
<html> |
|
<head> |
|
<style> |
|
body { |
|
margin: 0; |
|
font-family: "Helvetica", sans-serif; |
|
} |
|
text { |
|
text-anchor: middle; |
|
fill: #fff; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script> |
|
var alphabet = "abcdefghijklmnopqrstuvwxyz".split(""); |
|
|
|
var width = window.innerWidth, height = window.innerHeight; |
|
|
|
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height); |
|
|
|
var pack = d3.pack() |
|
.size([width, height]) |
|
.padding(1.5); |
|
|
|
redraw(randomizeData()); |
|
d3.interval(function(){ |
|
redraw(randomizeData()); |
|
}, 1500); |
|
|
|
function redraw(classes){ |
|
|
|
// transition |
|
var t = d3.transition() |
|
.duration(750); |
|
|
|
// hierarchy |
|
var h = d3.hierarchy({children: classes}) |
|
.sum(function(d) { return d.size; }) |
|
|
|
//JOIN |
|
var circle = svg.selectAll("path") |
|
.data(pack(h).leaves(), function(d){ return d.data.name; }); |
|
|
|
var text = svg.selectAll("text") |
|
.data(pack(h).leaves(), function(d){ return d.data.name; }); |
|
|
|
//EXIT |
|
circle.exit() |
|
.style("fill", "#b26745") |
|
.transition(t) |
|
.attr("d", function(d){ return circleToPath(d.x, d.y, 1e-6); }) |
|
.remove(); |
|
|
|
text.exit() |
|
.transition(t) |
|
.attr("opacity", 1e-6) |
|
.remove(); |
|
|
|
//UPDATE |
|
circle |
|
.transition(t) |
|
.attr("d", function(d){ return circleToPath(d.x, d.y, d.r); }) |
|
.style("fill", "#3a403d"); |
|
|
|
text |
|
.transition(t) |
|
.attr("x", function(d){ return d.x; }) |
|
.attr("y", function(d){ return d.y; }); |
|
|
|
//ENTER |
|
circle.enter().append("path") |
|
.attr("d", function(d){ return circleToPath(d.x, d.y, 1e-6); }) |
|
.style("fill", "#fff") |
|
.transition(t) |
|
.attr("d", function(d){ return circleToPath(d.x, d.y, d.r); }) |
|
.style("fill", "#45b29d"); |
|
|
|
text.enter().append("text") |
|
.attr("opacity", 1e-6) |
|
.attr("x", function(d){ return d.x; }) |
|
.attr("y", function(d){ return d.y; }) |
|
.text(function(d){ return d.data.name; }) |
|
.transition(t) |
|
.attr("opacity", 1); |
|
} |
|
|
|
function randomizeData(){ |
|
var d0 = shuffle(alphabet), |
|
d1 = [], |
|
d2 = []; |
|
for (var i = 0; i < random(1, alphabet.length); i++){ |
|
d1.push(d0[i]); |
|
} |
|
d1.forEach(function(d){ |
|
d2.push({name: d, size: random(1, 10)}) |
|
}); |
|
return d2; |
|
} |
|
|
|
function random(min, max) { |
|
return Math.floor(Math.random() * (max - min + 1)) + min; |
|
} |
|
|
|
function shuffle(array) { |
|
var m = array.length, t, i; |
|
|
|
// While there remain elements to shuffle… |
|
while (m) { |
|
|
|
// Pick a remaining element… |
|
i = Math.floor(Math.random() * m--); |
|
|
|
// And swap it with the current element. |
|
t = array[m]; |
|
array[m] = array[i]; |
|
array[i] = t; |
|
} |
|
|
|
return array; |
|
} |
|
|
|
function circleToPath(cx, cy, r){ |
|
return "M" + cx + "," + cy + "m" + (-r) + ",0a" + r + "," + r + " 0 1,0 " + (r * 2) + ",0a" + r + "," + r + " 0 1,0 " + (-r * 2) + ",0"; |
|
} |
|
|
|
</script> |
|
</body> |
|
</html> |