Click to expand or collapse nodes in the tree. Built with D3.js.
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> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"> | |
<title>Production Metrics Graph</title> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<!--script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.25.0"></script--> | |
<!--script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js?1.25.0"></script--> | |
<!--script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?1.25.0"></script--> | |
<style type="text/css"> | |
circle.node { | |
cursor: pointer; | |
stroke: #3182bd; | |
stroke-width: 1.5px; | |
} | |
line.link { | |
fill: none; | |
stroke: #9ecae1; | |
stroke-width: 1.5px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="chart"></div> | |
<script type="text/javascript"> | |
var w = 960, | |
h = 500, | |
node, | |
link, | |
root; | |
var force = d3.layout.force() | |
.on("tick", tick) | |
.size([w, h]); | |
var vis = d3.select("#chart").append("svg:svg") | |
.attr("width", w) | |
.attr("height", h); | |
/* | |
var x_scale = d3.scale.linear() | |
.domain([-0.5, -0.5]) | |
.range([0,960]); | |
var y_scale = d3.scale.linear() | |
.domain([0, 1]) | |
.range([0, 500]); | |
*/ | |
d3.json("prod.json", function(json) { | |
root = json; | |
var nodes = flatten(root); | |
var r_arr = nodes.map(function(d){return (Math.sqrt(d.base_rev) / 10)}); | |
var x_min = d3.min(nodes, rate); | |
var x_max = d3.max(nodes, rate); | |
var x_rad = 0.05 * (x_max - x_min); | |
var y_min = d3.min(nodes, rate); | |
var y_max = d3.max(nodes, rate); | |
var y_rad = 0.05 * (y_max - y_min); | |
x_scale = d3.scale.linear() | |
.domain([x_min - x_rad, x_max + x_rad]) | |
.range([0,960]); | |
y_scale = d3.scale.linear() | |
.domain([y_min - y_rad, y_max + y_rad]) | |
.range([0,500]); | |
update(); | |
}); | |
function update() { | |
var nodes = flatten(root), | |
links = d3.layout.tree().links(nodes); | |
// Restart the force layout. | |
force | |
.nodes(nodes) | |
.links(links) | |
.start(); | |
// Update the links… | |
link = vis.selectAll("line.link") | |
.data(links, function(d) { return d.target.id; }); | |
// Enter any new links. | |
link.enter().insert("svg:line", ".node") | |
.attr("class", "link") | |
.attr("x1", function(d) { return x_scale(rate(d.source)); }) | |
.attr("y1", function(d) { return y_scale(retention(d.source)); }) | |
.attr("x2", function(d) { return x_scale(rate(d.target)); }) | |
.attr("y2", function(d) { return y_scale(retention(d.target)); }); | |
// Exit any old links. | |
link.exit().remove(); | |
// Update the nodes… | |
node = vis.selectAll("circle.node") | |
.data(nodes, function(d) { return d.id; }) | |
.style("fill", color) | |
.attr("r", function(d) { return (!d.children && Math.sqrt(d.base_rev) / 10) || 4.5; }); | |
// Enter any new nodes. | |
node.enter().append("svg:circle") | |
.attr("class", "node") | |
.attr("cx", function(d) { return x_scale(0.00); }) | |
.attr("cy", function(d) { return y_scale(1.00); }) | |
.style("fill", color) | |
.attr("r", function(d) { return (!d.children && Math.sqrt(d.base_rev) / 10) || 4.5; }) | |
.on("click", click) | |
.call(force.drag) | |
.transition() | |
.attr("cx", function(d) { return x_scale(rate(d)); }) | |
.attr("cy", function(d) { return y_scale(retention(d)); }) | |
.duration(500) | |
.ease("elastic"); | |
// Exit any old nodes. | |
node.exit().remove(); | |
} | |
function tick() { | |
link.attr("x1", function(d) { return x_scale(rate(d.source)); }) | |
.attr("y1", function(d) { return y_scale(retention(d.source)); }) | |
.attr("x2", function(d) { return x_scale(rate(d.target)); }) | |
.attr("y2", function(d) { return y_scale(retention(d.target)); }); | |
node.attr("cx", function(d) { return x_scale(rate(d)); }) | |
.attr("cy", function(d) { return y_scale(retention(d)); }); | |
} | |
// Color leaf nodes orange, and packages white or blue. | |
function color(d) { | |
return d._children ? "#3182bd" : d.children ? "#c6dbef" : "#fd8d3c"; | |
} | |
function rate(d) { | |
return d.rate_rev / d.ret_rev; | |
} | |
function retention(d) { | |
return d.ret_rev / d.base_rev; | |
} | |
// Toggle children on click. | |
function click(d) { | |
if (d.children) { | |
d._children = d.children; | |
d.children = null; | |
} else { | |
d.children = d._children; | |
d._children = null; | |
} | |
update(); | |
} | |
// Returns a list of all nodes under the root. | |
function flatten(root) { | |
var nodes = [], i = 0; | |
function recurse(node) { | |
if (node.children) node.children.forEach(recurse); | |
if (!node.id) node.id = ++i; | |
nodes.push(node); | |
} | |
recurse(root); | |
return nodes; | |
} | |
</script> | |
</body> | |
</html> |
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
{ | |
"name": "Countrywide", "base_rev": 231000, "ret_rev": 193600, "rate_rev": 12900, "new_rev": 21600, | |
"children": [ | |
{ | |
"name": "Region A", "base_rev": 31000, "ret_rev": 26300, "rate_rev": 2400, "new_rev": 3600, | |
"children": [ | |
{"name": "Office A1", "base_rev": 10000, "ret_rev": 8500, "rate_rev": 1000, "new_rev": 1200 }, | |
{"name": "Office A2", "base_rev": 12000, "ret_rev": 9600, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office A3", "base_rev": 9000, "ret_rev": 8200, "rate_rev": 700, "new_rev": 1200 } | |
] | |
}, | |
{ | |
"name": "Region B", "base_rev": 94500, "ret_rev": 86000, "rate_rev": 4200, "new_rev": 7200, | |
"children": [ | |
{"name": "Office B1", "base_rev": 11000, "ret_rev": 9200, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office B2", "base_rev": 15000, "ret_rev": 13000, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office B3", "base_rev": 20000, "ret_rev": 18500, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office B4", "base_rev": 40000, "ret_rev": 37600, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office B5", "base_rev": 5000, "ret_rev": 4500, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office B6", "base_rev": 3500, "ret_rev": 3200, "rate_rev": 700, "new_rev": 1200 } | |
] | |
}, | |
{ | |
"name": "Region C", "base_rev": 63000, "ret_rev": 50300, "rate_rev": 2100, "new_rev": 3600, | |
"children": [ | |
{"name": "Office C1", "base_rev": 13000, "ret_rev": 10800, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office C2", "base_rev": 30000, "ret_rev": 25000, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office C3", "base_rev": 20000, "ret_rev": 14500, "rate_rev": 700, "new_rev": 1200 } | |
] | |
}, | |
{ | |
"name": "Region D", "base_rev": 16500, "ret_rev": 13000, "rate_rev": 2800, "new_rev": 4800, | |
"children": [ | |
{"name": "Office D1", "base_rev": 4000, "ret_rev": 3500, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office D2", "base_rev": 7000, "ret_rev": 5000, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office D3", "base_rev": 2000, "ret_rev": 1500, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office D4", "base_rev": 3500, "ret_rev": 3000, "rate_rev": 700, "new_rev": 1200 } | |
] | |
}, | |
{ | |
"name": "Region E", "base_rev": 22000, "ret_rev": 18000, "rate_rev": 1400, "new_rev": 2400, | |
"children": [ | |
{"name": "Office E1", "base_rev": 8000, "ret_rev": 6500, "rate_rev": 700, "new_rev": 1200 }, | |
{"name": "Office E2", "base_rev": 14000, "ret_rev": 11500, "rate_rev": 700, "new_rev": 1200 } | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment