Skip to content

Instantly share code, notes, and snippets.

@almsuarez
Last active January 18, 2018 21:19
Show Gist options
  • Save almsuarez/2f7219a4f52b572a3ca7da91a25681f9 to your computer and use it in GitHub Desktop.
Save almsuarez/2f7219a4f52b572a3ca7da91a25681f9 to your computer and use it in GitHub Desktop.
Modifying a Force Layout with buttons
license: gpl-3.0
<!DOCTYPE html>
<div id="option">
<input name="updateButton"
type="button"
value="Step 1"
onclick="update1()" />
<input name="updateButton"
type="button"
value="Step 2"
onclick="update2()" />
<input name="updateButton"
type="button"
value="Step 3"
onclick="update3()" />
<input name="revertButton"
type="button"
value="Reset"
onclick="resetData()" />
</div>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
color = d3.scaleOrdinal(d3.schemeCategory10);
var a = {id: "a"},
b = {id: "b"},
c = {id: "c"},
nodes = [a, b, c],
links = [];
var simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-1000))
.force("link", d3.forceLink(links).distance(200))
.force("x", d3.forceX())
.force("y", d3.forceY())
.alphaTarget(1)
.on("tick", ticked);
var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
link = g.append("g").attr("stroke", "#000").attr("stroke-width", 1.5).selectAll(".link"),
node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node");
restart();
function update1(){
links.push({source: a, target: b}); // Add a-b.
links.push({source: b, target: c}); // Add b-c.
links.push({source: c, target: a}); // Add c-a.
restart();
}
function update2(){
nodes.pop(); // Remove c.
links.pop(); // Remove c-a.
links.pop(); // Remove b-c.
restart();
}
function update3(){
nodes.push(c); // Re-add c.
links.push({source: b, target: c}); // Re-add b-c.
links.push({source: c, target: a}); // Re-add c-a.
restart();
}
function resetData(){
a = {id: "a"},
b = {id: "b"},
c = {id: "c"},
nodes = [a, b, c],
links = [];
restart();
}
// d3.timeout(function() {
// links.push({source: a, target: b}); // Add a-b.
// links.push({source: b, target: c}); // Add b-c.
// links.push({source: c, target: a}); // Add c-a.
// restart();
// }, 1000);
// d3.interval(function() {
// nodes.pop(); // Remove c.
// links.pop(); // Remove c-a.
// links.pop(); // Remove b-c.
// restart();
// }, 2000, d3.now());
// d3.interval(function() {
// nodes.push(c); // Re-add c.
// links.push({source: b, target: c}); // Re-add b-c.
// links.push({source: c, target: a}); // Re-add c-a.
// restart();
// }, 2000, d3.now() + 1000);
function restart() {
// Apply the general update pattern to the nodes.
node = node.data(nodes, function(d) { return d.id;});
node.exit().transition()
.attr("r", 0)
.remove();
node = node.enter().append("circle")
.attr("fill", function(d) { return color(d.id); })
.call(function(node) { node.transition().attr("r", 8); })
.merge(node);
// Apply the general update pattern to the links.
link = link.data(links, function(d) { return d.source.id + "-" + d.target.id; });
// Keep the exiting links connected to the moving remaining nodes.
link.exit().transition()
.attr("stroke-opacity", 0)
.attrTween("x1", function(d) { return function() { return d.source.x; }; })
.attrTween("x2", function(d) { return function() { return d.target.x; }; })
.attrTween("y1", function(d) { return function() { return d.source.y; }; })
.attrTween("y2", function(d) { return function() { return d.target.y; }; })
.remove();
link = link.enter().append("line")
.call(function(link) { link.transition().attr("stroke-opacity", 1); })
.merge(link);
// Update and restart the simulation.
simulation.nodes(nodes);
simulation.force("link").links(links);
simulation.alpha(1).restart();
}
function ticked() {
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return 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; });
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment