###Clustered Force Layout using D3 v4
Modified from Mike Bostock's original.
Looks more like the version with custom gravity.
Compare with Shan Carter's v4 adaptation.
###Clustered Force Layout using D3 v4
Modified from Mike Bostock's original.
Looks more like the version with custom gravity.
Compare with Shan Carter's v4 adaptation.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <title>Clustered Force Layout</title> | |
| <body> | |
| <script src="//d3js.org/d3.v4.min.js"></script> | |
| <script> | |
| var width = 960, | |
| height = 500, | |
| maxRadius = 12; | |
| var n = 1000, // total number of circles | |
| m = 10; // number of distinct clusters | |
| var color = d3.scaleOrdinal(d3.schemeCategory10) | |
| .domain(d3.range(m)); | |
| // The largest node for each cluster. | |
| var clusters = new Array(m); | |
| var nodes = d3.range(n).map(function() { | |
| var i = Math.floor(Math.random() * m), | |
| r = Math.sqrt((i + 1) / m * -Math.log(Math.random())) * maxRadius, | |
| d = {cluster: i, radius: r}; | |
| if (!clusters[i] || (r > clusters[i].radius)) clusters[i] = d; | |
| return d; | |
| }); | |
| var forceCollide = d3.forceCollide() | |
| .radius(function(d) { return d.radius + 1.5; }) | |
| .iterations(1); | |
| var force = d3.forceSimulation() | |
| .nodes(nodes) | |
| .force("center", d3.forceCenter()) | |
| .force("collide", forceCollide) | |
| .force("cluster", forceCluster) | |
| .force("gravity", d3.forceManyBody(30)) | |
| .force("x", d3.forceX().strength(.7)) | |
| .force("y", d3.forceY().strength(.7)) | |
| .on("tick", tick); | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| .append('g') | |
| .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); | |
| var circle = svg.selectAll("circle") | |
| .data(nodes) | |
| .enter().append("circle") | |
| .attr("r", function(d) { return d.radius; }) | |
| .style("fill", function(d) { return color(d.cluster); }) | |
| // TODO: Update for v4 | |
| // .call(force.drag); | |
| function tick() { | |
| circle | |
| .attr("cx", function(d) { return d.x; }) | |
| .attr("cy", function(d) { return d.y; }); | |
| } | |
| function forceCluster(alpha) { | |
| for (var i = 0, n = nodes.length, node, cluster, k = alpha * 1; i < n; ++i) { | |
| node = nodes[i]; | |
| cluster = clusters[node.cluster]; | |
| node.vx -= (node.x - cluster.x) * k; | |
| node.vy -= (node.y - cluster.y) * k; | |
| } | |
| } | |
| </script> |