This simple interaction demonstrates how to change links in a Force-Directed Graph using D3.js version 4. It follows the new General Update Pattern in order to add and remove elements as needed.
Last active
July 24, 2017 05:31
-
-
Save colbenkharrl/21b3808492b93a21de841bc5ceac4e47 to your computer and use it in GitHub Desktop.
Switching Links on Force-Directed Graph (D3 V4)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nodes": [ | |
{ "id": "0", "group": "1" }, | |
{ "id": "1", "group": "2" }, | |
{ "id": "2", "group": "2" }, | |
{ "id": "3", "group": "2" }, | |
{ "id": "4", "group": "2" }, | |
{ "id": "5", "group": "3" }, | |
{ "id": "6", "group": "3" }, | |
{ "id": "7", "group": "3" }, | |
{ "id": "8", "group": "3" } | |
], | |
"links1": [ | |
{ "source": "0", "target": "1", "id": "0"}, | |
{ "source": "0", "target": "2", "id": "1"}, | |
{ "source": "0", "target": "3", "id": "2"}, | |
{ "source": "0", "target": "4", "id": "3"}, | |
{ "source": "1", "target": "5", "id": "4"}, | |
{ "source": "2", "target": "6", "id": "5"}, | |
{ "source": "3", "target": "7", "id": "6"}, | |
{ "source": "4", "target": "8", "id": "7"}, | |
{ "source": "1", "target": "8", "id": "8"}, | |
{ "source": "2", "target": "5", "id": "9"}, | |
{ "source": "3", "target": "6", "id": "10"}, | |
{ "source": "4", "target": "7", "id": "11"} | |
], | |
"links2": [ | |
{ "source": "0", "target": "5", "id": "0"}, | |
{ "source": "0", "target": "6", "id": "1"}, | |
{ "source": "0", "target": "7", "id": "2"}, | |
{ "source": "0", "target": "8", "id": "3"}, | |
{ "source": "5", "target": "6", "id": "4"}, | |
{ "source": "5", "target": "8", "id": "5"}, | |
{ "source": "7", "target": "6", "id": "6"}, | |
{ "source": "7", "target": "8", "id": "7"}, | |
{ "source": "1", "target": "5", "id": "8"}, | |
{ "source": "2", "target": "6", "id": "9"}, | |
{ "source": "3", "target": "7", "id": "10"}, | |
{ "source": "4", "target": "8", "id": "11"} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<meta charset="UTF-8"> | |
<style> | |
/* Style Definitions */ | |
button { | |
position: absolute; | |
top: 1em; | |
left: 1em; | |
} | |
.node { | |
stroke: white; | |
stroke-width: 2px; | |
} | |
.link { | |
stroke: gray; | |
stroke-width: 2px; | |
} | |
</style> | |
<button type="button" id="switch-btn">Switch Links</button> | |
<svg width="960" height="500"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
// graph data store | |
var graph; | |
// state variable for current link set | |
var firstLinks = true; | |
// svg and sizing | |
var svg = d3.select("svg"), | |
width = +svg.attr("width"), | |
height = +svg.attr("height"); | |
// d3 color scheme | |
var color = d3.scaleOrdinal(d3.schemeCategory10); | |
// elements for data join | |
var link = svg.append("g").selectAll(".link"), | |
node = svg.append("g").selectAll(".node"); | |
// simulation initialization | |
var simulation = d3.forceSimulation() | |
.force("link", d3.forceLink() | |
.id(function(d) { return d.id; })) | |
.force("charge", d3.forceManyBody() | |
.strength(function(d) { return -500;})) | |
.force("center", d3.forceCenter(width / 2, height / 2)); | |
// button event handling | |
d3.select("#switch-btn").on("click", function() { | |
firstLinks = !firstLinks; | |
update(); | |
}); | |
// load and save data | |
d3.json("blocks-data.json", function(err, g) { | |
if (err) throw err; | |
graph = g; | |
update(); | |
}); | |
// follow v4 general update pattern | |
function update() { | |
// Update link set based on current state | |
// DATA JOIN | |
link = link.data(firstLinks ? graph.links1 : graph.links2); | |
// EXIT | |
// Remove old links | |
link.exit().remove(); | |
// ENTER | |
// Create new links as needed. | |
link = link.enter().append("line") | |
.attr("class", "link") | |
.merge(link); | |
// DATA JOIN | |
node = node.data(graph.nodes); | |
// EXIT | |
node.exit().remove(); | |
// ENTER | |
node = node.enter().append("circle") | |
.attr("class", "node") | |
.attr("r", 10) | |
.attr("fill", function(d) {return color(d.group);}) | |
.call(d3.drag() | |
.on("start", dragstarted) | |
.on("drag", dragged) | |
.on("end", dragended) | |
) | |
.merge(node); | |
// Set nodes, links, and alpha target for simulation | |
simulation | |
.nodes(graph.nodes) | |
.on("tick", ticked); | |
simulation.force("link") | |
.links(firstLinks ? graph.links1 : graph.links2); | |
simulation.alphaTarget(0.3).restart(); | |
} | |
// drag event handlers | |
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; | |
} | |
// tick event handler (nodes bound to container) | |
function ticked() { | |
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; }); | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Click to see more! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment