Built with blockbuilder.org.
Click on Open in a new window to see responsiveness.
Last active
January 11, 2016 01:49
-
-
Save coderextreme/1333c72dd1301f60be24 to your computer and use it in GitHub Desktop.
Responsive Double Hierarchy DAG cluster
This file contains hidden or 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> | |
<meta charset="utf-8"> | |
<title>Double Hierarchy DAG</title> | |
<style> | |
body { | |
width:100%; | |
height:100%; | |
} | |
</style> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
</head> | |
<body> | |
<div style="width:100%;height:100%"></div> | |
<script type="text/javascript"> | |
function setup(json) { | |
var domain = []; | |
var range = []; | |
var i = 0; | |
for (ch in json.children) { | |
child = json.children[ch]; | |
domain.push(child.name); | |
range.push(i); | |
for (gc in child.children) { | |
grandchild = child.children[gc]; | |
domain.push(grandchild.name); | |
range.push(i); | |
} | |
i++; | |
} | |
var map = d3.scale.ordinal() | |
.domain(domain) | |
.range(range); | |
d3.select(window) | |
.on("resize", function() { | |
/* | |
width = window.innerWidth; | |
height = window.innerHeight; | |
d3.select("svg") | |
.attr("width", width) | |
.attr("height", height); | |
*/ | |
d3.select("svg").remove(); | |
redraw(json, map); | |
}) | |
redraw(json, map); | |
} | |
function getLinks(json, count) { | |
var map = {}; | |
var other = []; | |
json.forEach(function(d) { | |
map[d.name] = d; | |
count[d.name] = 0; | |
}); | |
json.forEach(function(d) { | |
if (d.other) d.other.forEach(function(o) { | |
count[o.name]++; | |
other.push({source: map[d.name], target: map[o.name]}); | |
}); | |
// once the big circles have been plotted, move y inward | |
if (d.depth == 2) { | |
d.y /= 1.15; | |
} | |
}); | |
json.forEach(function(d) { | |
if (d.depth == 2 && count[d.name] > 1) { | |
d.x -= count[d.name] + 0.5; | |
} | |
}); | |
return other; | |
} | |
function redraw(json, map) { | |
var width = $("div").width() || Math.max(document.documentElement.clientWidth, window.innerWidth || 0); | |
var height = $("div").height() || Math.max(document.documentElement.clientHeight, window.innerHeight || 0) | |
var min = width < height ? width : height; | |
var rx = width/2; | |
var ry = height/2; | |
var rm = min/2; | |
var color = d3.scale.category20(); | |
var pi = Math.PI; | |
var bundle = d3.layout.bundle(); | |
var line = d3.svg.line.radial() | |
.interpolate("bundle") | |
.tension(0.50) | |
.radius(function(d) { return d.y; }) | |
.angle(function(d) { return d.x / 180 * pi; }); | |
var arc = d3.svg.arc() | |
.innerRadius(0) | |
.outerRadius(function(d,i) {return min/7; }) | |
.startAngle(function(d,i) { return 0;}) | |
.endAngle(function(d) { return 2*pi;}); | |
var svg = d3.select("div") | |
.append("svg:svg") | |
.attr("viewBox", "0 0 " + width + " " + height); | |
svg.append('defs') | |
.append('path') | |
.attr("d", arc) | |
.attr("id", "curvedPath"); | |
var center = svg.append("svg:g") | |
.attr("transform", "translate(" + rx + "," + ry + ")"); | |
var cluster = d3.layout.cluster() | |
.separation(function(d) { return 1;}) | |
.size([360, min/4]) | |
.sort(null); | |
var nodes = cluster.nodes(json); | |
var node = center.selectAll("g.node") | |
.data(nodes) | |
.enter().append("svg:g") | |
node.append("svg:text") | |
.attr("text-anchor", function(d) { return "middle"; }) | |
.append('textPath') | |
.attr("startOffset", function(d) { | |
var percent = 100*d.x/360; | |
return (percent >= 50 ? percent - 50 : percent + 50) +"%"; | |
}) | |
.attr("xlink:href", function(d) { return (d.depth == 1 ? "#curvedPath" : null); }) | |
.attr("fill", function(d, i) { return color(map(d.name)); } ) | |
.style("font-size", min/45 + "px") | |
.text(function(d) { return (d.depth == 1 ? d.name : ""); }); | |
var g = node.append("svg:g") | |
.attr("class", "node") | |
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ") translate(" + d.y + ")"; }); | |
g.append("svg:circle") | |
.attr("r", function(d) { return d.size * min / 900; }) | |
.attr("fill", function (d,i) { return color(map(d.name));}); | |
g.append("svg:text") | |
.attr("dx", function(d) { return d.x < 180 ? 18 : -18; }) | |
.attr("dy", ".31em") | |
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) | |
.attr("transform", function(d) { return d.x < 180 ? "" : "rotate(180)"; }) | |
.style("font-size", min/45 + "px") | |
.text(function(d) { return (d.depth == 2 ? d.name : ""); }) | |
// minor links | |
var count = {}; | |
var links = getLinks(nodes, count); | |
var splines = bundle(links); | |
center.selectAll(".path") | |
.data(links) | |
.enter().append("svg:path") | |
.attr("stroke", function(d) {return color(map(d.source.name));}) | |
.attr("fill", "none") | |
.attr("class", "path") | |
.attr("d", function(d, i) { | |
var o = splines[i][3]; | |
if (o.depth == 2 && count[o.name] > 1) { | |
o.x += 2.5; | |
} | |
return line(splines[i]); }); | |
// set o.x back | |
for (i in splines) { | |
var o = splines[i][3]; | |
if (o.depth == 2 && count[o.name] > 1) { | |
o.x -= 2.5; | |
} | |
} | |
// minor circles | |
center.selectAll(".circle") | |
.data(links) | |
.enter().append("svg:g") | |
.attr("class", "circle") | |
.attr("transform", function(d,i) { | |
var o = splines[i][3]; | |
if (o.depth == 2 && count[o.name] > 1) { | |
o.x += 2.5; | |
} | |
return "rotate(" + (o.x - 90) + ") translate(" + d.target.y + ")"; | |
}) | |
.append("svg:circle") | |
.attr("r", function(d) { return d.source.size * min / 900; }) | |
.attr("fill", function (d,i) { return color(map(d.source.name));}); | |
} | |
$(document).ready(function() { | |
d3.json("sw.json", function(error, json) { | |
if (error) return console.warn(error); | |
setup(json); | |
}); | |
}); | |
</script> | |
<script type="text/javascript"> | |
// Hack to make this example display correctly in an iframe on bl.ocks.org | |
d3.select(self.frameElement).style("height", "700px"); | |
</script> | |
</body> | |
</html> |
This file contains hidden or 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
{ | |
"name": "Center", | |
"size": 0, | |
"children": [ | |
{ | |
"name": "Research", | |
"size": 5, | |
"children": [ | |
{ "name": "Blanc Brain", "size": 15}, | |
{ "name": "Consultation", "size": 15} | |
] | |
}, | |
{ | |
"name": "Plan", | |
"size": 5, | |
"children": [ | |
{ "name": "Information Architecture", "size": 15}, | |
{ "name": "Accessibility", "size": 15} | |
], | |
"other": [ | |
{ "name": "Consultation", "size": 5}, | |
{ "name": "High availability", "size": 5}, | |
{ "name": "Open Source", "size": 5} | |
] | |
}, | |
{ | |
"name": "Create", | |
"size": 5, | |
"children": [ | |
{ "name": "Creative/Design", "size": 15}, | |
{ "name": "User Interface", "size": 15}, | |
{ "name": "Content Creation", "size": 15}, | |
{ "name": "Photography & Video Production", "size": 15}, | |
{ "name": "Infographics", "size": 15} | |
], | |
"other": [ | |
{ "name": "Responsive Design", "size": 5}, | |
{ "name": "Information Architecture", "size": 5}, | |
{ "name": "Accessibility", "size": 5} | |
] | |
}, | |
{ | |
"name": "Build", | |
"size": 5, | |
"children": [ | |
{ "name": "Website Development", "size": 15}, | |
{ "name": "Web App Development", "size": 15}, | |
{ "name": "Bespoke CMS", "size": 15}, | |
{ "name": "Django", "size": 15}, | |
{ "name": "Python", "size": 15}, | |
{ "name": "Open Source", "size": 15}, | |
{ "name": "Responsive Design", "size": 15} | |
], | |
"other": [ | |
{ "name": "Information Architecture", "size": 5}, | |
{ "name": "Accessibility", "size": 5} | |
] | |
}, | |
{ | |
"name": "Launch", | |
"size": 5, | |
"children": [ | |
{ "name": "High availability", "size": 15}, | |
{ "name": "Hosting", "size": 15}, | |
{ "name": "Support & Maintenance", "size": 15} | |
], | |
"other": [ | |
{ "name": "Blanc Brain", "size": 5} | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment