Created
December 2, 2013 17:01
-
-
Save spendres/7752696 to your computer and use it in GitHub Desktop.
D3 Node plot.
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
<html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> | |
<style> | |
.node circle { | |
fill: #fff; | |
stroke: steelblue; | |
stroke-width: 1.5px; | |
} | |
.node { | |
font: 14px "HelveticaNeue-Light"; | |
} | |
.node:nth-of-type(1) { | |
font: 16px "HelveticaNeue-Light"; | |
} | |
.legend { | |
font: 18px "HelveticaNeue-Light"; | |
font-weight:200; | |
font-style:oblique; | |
//fill: #00b; | |
} | |
.suffix { | |
font-weight:300; | |
fill:rgb(12,162,234); | |
} | |
rect.common { | |
fill:rgb(237,237,237); | |
z-index: -10; | |
} | |
rect.phenomenon { | |
fill:rgb(237,245,250); | |
z-index: -10; | |
} | |
.bracket { | |
fill: none; | |
stroke: #00b; | |
stroke-width: 1.0px; | |
} | |
.link { | |
fill: none; | |
stroke: #ddd; | |
stroke-width: 1.5px; | |
} | |
.link:nth-child(1) { | |
fill: none; | |
stroke: #ddd; | |
stroke-width: 1.5px; | |
} | |
body { | |
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Arial, Helvetica , "Lucida Grande", sans-serif; | |
font-weight: 300; | |
} | |
</style> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script id="flare" type="application/json"> | |
{ | |
"name":"exhaustless\ntakeoffs", | |
"children":[ | |
{ | |
"name": "separate takeoffs\nfrom landings", | |
"tech":"common", | |
"children":[ | |
{ | |
"name":"simultaneous landings\nand takeoffs", | |
"tech":"common", | |
"children":[ | |
{ | |
"name":"more takeoff slots", | |
"tech":"common", | |
"children":[ | |
{"name":"increased\ncapacity"} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "increase acceleration\nrate", | |
"children":[ | |
{"name":"less distance and time\nrequired for takeoff", | |
"children":[ | |
{ | |
"name":"fewer\nbird strikes", | |
"children":[ | |
{"name":"increased\nsafety"} | |
] | |
}, | |
{ | |
"name":"shorter takeoff slots", | |
"children":[ | |
{"name":"increased\ncapacity"}, | |
{"name":"increased\nproductivity"} | |
] | |
}, | |
{ | |
"name":"less sprawl", | |
"children":[ | |
{"name":"increased\nproductivity"} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "increase takeoff\nvelocity", | |
"children":[ | |
{ | |
"name":"faster climb to cruise", | |
"children":[ | |
{ | |
"name":"reduce noise during\ntakeoff and climb", | |
"children":[ | |
{"name":"better\nquality of life"} | |
] | |
}, | |
{ | |
"name":"fewer\nbird strikes", | |
"children":[ | |
{"name":"increased\nsafety"} | |
] | |
} | |
] | |
}, | |
{ | |
"name":"increase stall margin", | |
"children":[ | |
{"name":"increased\nsafety"} | |
] | |
}, | |
{ | |
"name":"wind direction\nindependence", | |
"children":[ | |
{ | |
"name":"more operational\nflexibility", | |
"children":[ | |
{ | |
"name":"increased\nproductivity" | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name":"reduce jet fuel\nburned during\ntakeoff and climb", | |
"children":[ | |
{ | |
"name":"reduce exhaust from\ntakeoff and climb", | |
"children":[ | |
{"name":"better\nquality of life"}, | |
{"name":"reduced\ncarbon\nemissions"} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "use grid energy\ninstead of jet fuel", | |
"children":[ | |
{ | |
"name":"reduce jet fuel\nburned during\ntakeoff and climb", | |
"children":[ | |
{ | |
"name":"reduce noise during\ntakeoff and climb", | |
"children":[ | |
{"name":"better\nquality of life"}, | |
{"name":"increased\ncapacity"} | |
] | |
}, | |
{ | |
"name":"reduce exhaust from\ntakeoff and climb", | |
"children":[ | |
{"name":"better\nquality of life"}, | |
{"name":"reduced\ncarbon\nemissions"} | |
] | |
}, | |
{ | |
"name":"reduce chronic\nhealth problems", | |
"children":[ | |
{"name":"better\nquality of life"}, | |
{"name":"increased\neconomic\ngrowth"} | |
] | |
} | |
] | |
}, | |
{ | |
"name":"increase energy\nefficiency", | |
"children":[ | |
{ | |
"name":"create local grid\nand operational\njobs", | |
"children":[ | |
{"name":"increased\neconomic\ngrowth"} | |
] | |
} | |
,{ | |
"name":"reduced\ncarbon\nemissions" | |
} | |
] | |
} | |
] | |
} | |
] | |
} | |
</script> | |
</head> | |
<body> | |
<script type="text/javascript"> | |
function setup() { | |
var removeDups = function (d) { | |
var count = []; | |
var preen = []; | |
var depth = 0; | |
var nodes = d.slice(0); | |
//nodes.reverse(); | |
d.forEach( function(dd,index) { | |
dd.id = index; | |
//console.log("dd: ",dd.name,dd.id); | |
depth = ( (dd.depth > depth) ? dd.depth : depth ); | |
(count[dd.name]==undefined) ? (count[dd.name]=[dd.id]) : ( count[dd.name].push(dd.id) ); | |
//(count[dd.name]==undefined) ? (count[dd.name]=[dd.id]) : (preen.push(dd.id), ); | |
}); | |
while (depth > 0) { | |
nodes.forEach( function(dd,index) { | |
if(dd.depth == depth){ | |
if( count[dd.name].length > 1 ){ | |
var modeIndex = count[dd.name].length>>1; | |
var merged = count[dd.name].splice(modeIndex,1); | |
var duplicates = count[dd.name]; //.splice(1); | |
preen = preen.concat(duplicates); | |
duplicates.forEach( function(duplicate,index){ | |
var children = nodes[duplicate].parent.children; | |
children.forEach( function(child,ii){ | |
if(child.id == duplicate){ | |
nodes[duplicate].parent.children[ii] = nodes[merged]; | |
} | |
//console.log(nodes[duplicate].parent); | |
}); | |
}); | |
} | |
} | |
}); | |
depth--; | |
} | |
preen = preen.filter(function (e, i, arr) { | |
return preen.lastIndexOf(e) === i; | |
}); | |
preen.sort(function(a,b){return b - a}); | |
preen.forEach( function(dd,index) { nodes.splice(dd,1)} ); | |
return nodes; | |
}; | |
var insertLinebreaks = function (d) { | |
var el = d3.select(this); | |
var words = d.name.split('\n'); | |
el.text(''); | |
for (var i = 0; i < words.length; i++) { | |
var tspan = el.append('tspan').text(words[i]); | |
if (i > 0) | |
tspan.attr('x', "-.2em").attr('dy', '15'); | |
} | |
}; | |
var insertColorSuffix = function (d) { | |
var el = d3.select(this); | |
var words = d.name.split('\n'); | |
if (words[0] == 'exhaustless'){ | |
el.text('exhaust'); | |
var tspan = el.append('tspan').text('less').attr("class","suffix"); | |
tspan = el.append('tspan').text('\n'+words[1]); | |
tspan.attr('x', "-.2em").attr('dy', '15'); | |
} | |
}; | |
var width = 760, | |
height = 560; | |
var cluster = d3.layout.tree() | |
.size([height, width-50]); | |
var diagonal = d3.svg.diagonal() | |
.projection(function(d) { return [d.y, d.x]; }); | |
var radius = 5.5; | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("g") | |
.attr("transform", "translate(40,50) scale(.85)"); | |
svg.append("rect") | |
.attr("class", "common") | |
.attr("width",width*1.1) | |
.attr("height","14%") | |
.attr("transform", function(d) { return "translate(" + -25 + "," + -40 + ")"; }); | |
svg.append("rect") | |
.attr("class", "phenomenon") | |
.attr("width",width*1.1) | |
.attr("height","100%") | |
.attr("transform", function(d) { return "translate(" + -25 + "," + 45 + ")"; }); | |
var data = JSON.parse($("#flare").html()); | |
var nodes = cluster.nodes(data); | |
nodes = removeDups(nodes); | |
var maxDepth = 0; | |
var byDepth = {}; | |
depth = nodes.forEach( function(n,index) { | |
maxDepth = (n.depth > maxDepth) ? n.depth : maxDepth; | |
(byDepth[n.depth]==undefined) ? (byDepth[n.depth]=[n]) : byDepth[n.depth].push(n); | |
}); | |
var itemsToDistribute = byDepth[maxDepth]; | |
var increment = height*.8/(itemsToDistribute.length-1); | |
itemsToDistribute.forEach( function(n,index) { | |
n.x = increment*(index+1); | |
}); | |
links = cluster.links(nodes); | |
var link = svg.selectAll(".link") | |
.data(links) | |
.enter().append("path") | |
.attr("class", "link") | |
.attr("d", diagonal); | |
var node = svg.selectAll(".node") | |
.data(nodes) | |
.enter().append("g") | |
.attr("class", "node") | |
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) | |
node.append("circle") | |
.attr("r", radius); | |
node.append("text") | |
.attr("dx", function(d) { return "-.2em"; }) | |
.attr("dy", function(d) { | |
var s = d.name.split(" "); | |
// work around | |
if(s[0]=="wind" || s[0] =="create"){ | |
return "1.5em"; | |
} | |
return (d.name.split("\n").length*-1.0) + "em"; | |
}) | |
.attr("font-family","sans-serif") | |
.attr("font-weight","200") | |
.text(function(d) { return d.name; }); | |
svg.selectAll("g text").each(insertLinebreaks); | |
svg.selectAll("g text").each(insertColorSuffix); | |
svg.append("text") | |
.attr("dx", function(d) { return "0em"; }) | |
.attr("dy", "4.2em") | |
.attr("class","legend") | |
.text(function(d) { return "exhaust"; }) | |
.append("tspan") | |
.text(function(d) { return "less"; }) | |
.attr("class","legend suffix"); | |
svg.append("text") | |
.attr("dx", function(d) { return "0em"; }) | |
.attr("dy", "5.2em") | |
.attr("class","legend") | |
.text(function(d) { return "phenomenon"; }); | |
svg.append("text") | |
.attr("dx", function(d) { return "0em"; }) | |
.attr("dy", ".2em") | |
.attr("class","legend") | |
.text(function(d) { return "common to"; }); | |
svg.append("text") | |
.attr("dx", function(d) { return "0em"; }) | |
.attr("dy", "1.2em") | |
.attr("class","legend") | |
.text(function(d) { return "all solutions"; }); | |
//d3.select(self.frameElement).style("height", height + "px"); | |
} | |
window.onload = setup(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment