Skip to content

Instantly share code, notes, and snippets.

@denisemauldin
Created September 28, 2018 23:01
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 denisemauldin/e0a0c232f7a7f665fca87f395501049a to your computer and use it in GitHub Desktop.
Save denisemauldin/e0a0c232f7a7f665fca87f395501049a to your computer and use it in GitHub Desktop.
d3v5 Force Simulation complex groups
license: mit
<!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 width = document.querySelector("svg").clientWidth;
var height = document.querySelector("svg").clientHeight;
var nodeNumber = 30;
var nodesData = [];
for (var i = 0; i < nodeNumber; i++) {
nodesData.push({
"index": i,
"x": width * Math.random(),
"y": height * Math.random(),
"r": 10
});
}
var linksData = [];
var i = 0;
for (var j = i + 1; j < nodeNumber; j++) {
linksData.push({
"source": i,
"target": j,
"l": Math.random() * 150 + 5 + nodesData[i].r + nodesData[j].r
});
}
// 2. svg draw
var link = d3.select("svg")
.selectAll("line")
.data(linksData)
.enter()
.append("line")
.attr("stroke-width", 1)
.attr("stroke", "black");
var node = d3.select("svg")
.selectAll("circle")
.data(nodesData)
.enter()
.append("circle")
.attr("r", function (d) {
return d.r
})
.attr("fill", "LightSalmon")
.attr("stroke", "black")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
let groups = d3
.select("svg")
.selectAll(".group")
.data(nodesData)
.enter()
.append("g");
groups.append("circle").attr("r", 5);
groups.append("text").attr('x', 7).attr('y', 5).text(function (d, i) {
return `hello ${i}`;
});
// 3. forceSimulation setup
var simulation = d3.forceSimulation()
.force("link",
d3.forceLink()
.distance(function (d) {
return d.l;
})
.strength(0.03)
.iterations(16))
.force("collide",
d3.forceCollide()
.radius(function (d) {
return d.r;
})
.strength(0.7)
.iterations(16))
.force("charge", d3.forceManyBody().strength(-200))
.force("x", d3.forceX().strength(0.02).x(width / 2))
.force("y", d3.forceY().strength(0.02).y(height / 2));
simulation
.nodes(nodesData)
.on("tick", ticked);
simulation.force("link")
.links(linksData)
.id(function (d) {
return d.index;
});
// 4. forceSimulation ticked
function ticked() {
groups.attr("transform", function (d) {
return "translate(" + (d.x + 8) + "," + d.y + ")";
});
link
.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
node
.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
}
// 5. drag started
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment