In answer to a question on the d3 Slack channel #help
See also the simpler version in one move
Built with blockbuilder.org
license: mit |
In answer to a question on the d3 Slack channel #help
See also the simpler version in one move
Built with blockbuilder.org
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
</style> | |
</head> | |
<body> | |
<script> | |
// Feel free to change or delete any of the code you see in this editor! | |
var svg = d3.select("body").append("svg") | |
.attr("width", 960) | |
.attr("height", 500) | |
var data = d3.range(300).map(d => { | |
return { | |
x: 100 + 760 * Math.random(), | |
y: 100 + 300 * Math.random(), | |
w: 300 * Math.random(), | |
} | |
}) | |
function merge() { | |
var merged = 0; | |
data.forEach((d,i) => { | |
if (d.w == 0) return; | |
d.r = Math.sqrt(d.w); | |
data.slice(0, i).forEach((e,j) => { | |
if (e.w == 0) return; | |
var dx = e.x - d.x, | |
dy = e.y - d.y, | |
dist2 = dx * dx + dy * dy, | |
r2 = (d.r + e.r) * (d.r + e.r); | |
if (dist2 < r2) { | |
merged ++; | |
if (d.w >= e.w) { | |
d.x += dx * e.w / (d.w + e.w); | |
d.y += dy * e.w / (d.w + e.w); | |
d.w += e.w; | |
e.w = 0; | |
} else { | |
e.x -= dx * d.w / (d.w + e.w); | |
e.y -= dy * d.w / (d.w + e.w); | |
e.w += d.w; | |
d.w = 0; | |
} | |
} | |
}); | |
}); | |
return merged; | |
} | |
function display(stop){ | |
circles.transition() | |
.attr('r', d => Math.sqrt(d.w)) | |
.attr('cx', d => d.x) | |
.attr('cy', d => d.y); | |
circles.filter(d => !d.w) | |
.attr('opacity', 0) | |
.transition() | |
.remove(); | |
if (!stop) setTimeout(function(){ | |
var merged = merge(); | |
if (merged) { | |
console.log("merged", +merged); | |
display(); | |
} else { | |
console.log("ended"); | |
display("stop"); | |
circles | |
.transition() | |
.attr('opacity', 0.8); | |
} | |
}, 500); | |
} | |
var circles = svg.selectAll('circle') | |
.data(data) | |
.enter() | |
.append('circle') | |
.attr("fill", "#3498f7") | |
.attr("opacity", 0.5); | |
display(); | |
</script> | |
</body> |