Skip to content

Instantly share code, notes, and snippets.

@briandfoy
Last active December 30, 2015 14:39
Show Gist options
  • Save briandfoy/7843703 to your computer and use it in GitHub Desktop.
Save briandfoy/7843703 to your computer and use it in GitHub Desktop.
A visualization of a Perl module dependency graph
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<meta charset="utf-8">
<title>Perl module dependency graph</title>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.6.0"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?2.6.0"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js?2.6.0"></script>
<script type="text/javascript" src="jshashtable-3.0.js"></script>
</head>
<body>
<script type="text/javascript" charset="utf-8">
runIt( "https://gist.github.com/briandfoy/7843713/raw/da5e2bdaff0cff5051ed7be17cef6e7e9ff3d705/http-size_deps.json" );
function runIt( url ) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
var modules = JSON.parse(xmlhttp.responseText);
drawForce( modules );
}
}
};
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function drawForce(modules) {
var w = 960, h = 1000;
var labelDistance = 0;
var vis = d3.select("body")
.append("svg:svg")
.attr("width", w)
.attr("height", h);
var nodes = [];
var labelAnchors = [];
var labelAnchorLinks = [];
var links = [];
for(var i = 0; i < modules.names.length; i++) {
var node = { label : modules.names[i] };
nodes.push(node);
labelAnchors.push({ node : node });
labelAnchors.push({ node : node });
}
for(var i = 0; i < modules.links.length; i++) {
links.push({
source : modules.links[i][0],
target : modules.links[i][1],
weight : 1
});
}
for(var i = 0; i < nodes.length; i++) {
labelAnchorLinks.push({
source : i * 2,
target : i * 2 + 1,
weight : 1
});
};
var force = d3.layout.force()
.size([w, h])
.nodes(nodes)
.links(links)
.gravity(1)
.linkDistance(50)
.charge(-3000)
.linkStrength( function(x) { return x.weight * 10 });
force.start();
var force2 = d3.layout.force()
.nodes(labelAnchors)
.links(labelAnchorLinks)
.gravity(0)
.linkDistance(0)
.linkStrength(8)
.charge(-100)
.size([w, h]);
force2.start();
var link = vis.selectAll("line.link")
.data(links)
.enter()
.append("svg:line")
.attr("class", "link")
.style("stroke", "#CCC");
var node = vis.selectAll("g.node")
.data(force.nodes())
.enter()
.append("svg:g")
.attr("class", "node");
node.append("svg:circle")
.attr("r", 5)
.style("fill", "#F00")
.style("stroke", "#FFF")
.style("stroke-width", 3);
node.call(force.drag);
var anchorLink = vis.selectAll("line.anchorLink")
.data(labelAnchorLinks);
//.enter().append("svg:line").attr("class", "anchorLink").style("stroke", "#999");
var anchorNode = vis.selectAll("g.anchorNode")
.data(force2.nodes())
.enter()
.append("svg:g")
.attr("class", "anchorNode");
anchorNode.append("svg:circle")
.attr("r", 0)
.style("fill", "#FFF");
anchorNode.append("svg:text")
.text(function(d, i) { return i % 2 == 0 ? "" : d.node.label })
.style("fill", "#555")
.style("font-family", "Arial")
.style("font-size", 12);
var updateLink = function() {
this.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;
});
}
var updateNode = function() {
this.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
force.on("tick", function() {
force2.start();
node.call(updateNode);
anchorNode.each(function(d, i) {
if(i % 2 == 0) {
d.x = d.node.x;
d.y = d.node.y;
} else {
var b = this.childNodes[1].getBBox();
var diffX = d.x - d.node.x;
var diffY = d.y - d.node.y;
var dist = Math.sqrt(diffX * diffX + diffY * diffY);
var shiftX = b.width * (diffX - dist) / (dist * 2);
shiftX = Math.max(-b.width, Math.min(0, shiftX));
var shiftY = 5;
this.childNodes[1]
.setAttribute("transform", "translate(" + shiftX + "," + shiftY + ")");
}
});
anchorNode.call(updateNode);
link.call(updateLink);
anchorLink.call(updateLink);
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment