Created
January 9, 2014 18:15
-
-
Save HermanSontrop/8339125 to your computer and use it in GitHub Desktop.
d3 force example using svg images to display nodes
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> | |
<head> | |
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> | |
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script> | |
<script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script> | |
<style type="text/css"> | |
.link { stroke: #ccc; } | |
.nodetext { pointer-events: none; font: 10px sans-serif; } | |
body { width:100%; height:100%; margin:none; padding:none; } | |
#graph { width:1000px;height:500px; border:3px solid black;border-radius:12px; margin:auto; } | |
</style> | |
</head> | |
<body> | |
<div id="graph"></div> | |
</body> | |
<script type="text/javascript"> | |
function myGraph(el) { | |
// Add and remove elements on the graph object | |
this.addNode = function (id) { | |
nodes.push({"id":id}); | |
update(); | |
} | |
this.removeNode = function (id) { | |
var i = 0; | |
var n = findNode(id); | |
while (i < links.length) { | |
if ((links[i]['source'] == n)||(links[i]['target'] == n)) links.splice(i,1); | |
else i++; | |
} | |
nodes.splice(findNodeIndex(id),1); | |
update(); | |
} | |
this.addLink = function (source, target) { | |
links.push({"source":findNode(source),"target":findNode(target)}); | |
update(); | |
} | |
var findNode = function(id) { | |
for (var i in nodes) {if (nodes[i]["id"] === id) return nodes[i]}; | |
} | |
var findNodeIndex = function(id) { | |
for (var i in nodes) {if (nodes[i]["id"] === id) return i}; | |
} | |
// set up the D3 visualisation in the specified element | |
var w = $(el).innerWidth(), | |
h = $(el).innerHeight(); | |
var vis = this.vis = d3.select(el).append("svg:svg") | |
.attr("width", w) | |
.attr("height", h); | |
var force = d3.layout.force() | |
.gravity(.05) | |
.distance(100) | |
.charge(-500) | |
.size([w, h]); | |
var nodes = force.nodes(), | |
links = force.links(); | |
var update = function () { | |
var link = vis.selectAll("line.link") | |
.data(links, function(d) { return d.source.id + "-" + d.target.id; }); | |
link.enter().insert("line") | |
.attr("class", "link"); | |
link.exit().remove(); | |
var node = vis.selectAll("g.node") | |
.data(nodes, function(d) { return d.id;}); | |
var nodeEnter = node.enter().append("g") | |
.attr("class", "node") | |
.call(force.drag); | |
nodeEnter.append("image") | |
.attr("class", "circle") | |
.attr("xlink:href", "http://upload.wikimedia.org/wikipedia/commons/9/91/Adium.png") | |
.attr("x", "-8px") | |
.attr("y", "-8px") | |
.attr("width", "0px") | |
.attr("height", "0px") | |
.transition() | |
.ease("bounce") | |
.duration(2000) | |
.attr("width", "250px") | |
.attr("height", "250px"); | |
nodeEnter.append("text") | |
.attr("class", "nodetext") | |
.attr("dx", 12) | |
.attr("dy", ".35em") | |
.text(function(d) {return d.id}); | |
node.exit().remove(); | |
force.on("tick", function() { | |
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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); | |
}); | |
// Restart the force layout. | |
force.start(); | |
} | |
// Make it all go | |
update(); | |
} | |
graph = new myGraph("#graph"); | |
// You can do this from the console as much as you like... | |
graph.addNode("Cause"); | |
graph.addNode("Effect"); | |
graph.addLink("Cause", "Effect"); | |
graph.addNode("A"); | |
graph.addNode("B"); | |
graph.addLink("A", "B"); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment