d3.chart.sankey: Reusable D3 Sankey diagram using d3.Chart.
Interactive Sankey diagram.
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>d3.chart.sankey (interactive demo)</title> | |
<script src="//d3js.org/d3.v3.min.js"></script> | |
<script src="//cdn.rawgit.com/newrelic-forks/d3-plugins-sankey/master/sankey.js"></script> | |
<script src="//cdn.rawgit.com/misoproject/d3.chart/master/d3.chart.min.js"></script> | |
<script src="//cdn.rawgit.com/q-m/d3.chart.sankey/master/d3.chart.sankey.min.js"></script> | |
<style> | |
body { | |
width: 960px; | |
margin: auto; | |
} | |
#chart { | |
width: 960px; | |
height: 500px; | |
clear: both; | |
} | |
.node rect { | |
fill-opacity: .9; | |
shape-rendering: crispEdges; | |
} | |
.node text { | |
text-shadow: 0 1px 0 #fff; | |
} | |
.link { | |
fill: none; | |
stroke: #000; | |
stroke-opacity: .2; | |
} | |
.control { float: left; padding: 6px; } | |
.control label { display: block; } | |
.control input { width: 2.5em; } | |
.control button { border: outset 2px; } | |
.control button.active { border: inset 2px; } | |
#events { | |
height: 15ex; | |
overflow-y: scroll; | |
color: #444; | |
font-family: monospace; | |
border: 1px solid #eee; | |
} | |
#events span:first-child { | |
width: 10em; | |
display: inline-block; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="controls"> | |
<div class="control"> | |
<label for="source">data</label> | |
<select id="source"> | |
<option value="//cdn.rawgit.com/q-m/d3.chart.sankey/master/example/data/foo.json">foo.json</option> | |
<option value="//cdn.rawgit.com/q-m/d3.chart.sankey/master/example/data/energy.json">energy.json</option> | |
<option value="//cdn.rawgit.com/q-m/d3.chart.sankey/master/example/data/product.json">product.json</option> | |
</select> | |
</div> | |
<div class="control"> | |
<label for="nodeWidth">nodeWidth</label> | |
<input type="number" id="nodeWidth" step="1" value="8" min="0"> | |
</div> | |
<div class="control"> | |
<label for="nodePadding">nodePadding</label> | |
<input type="number" id="nodePadding" step="1" value="15" min="0"> | |
</div> | |
<div class="control"> | |
<label for="iterations">iterations</label> | |
<input type="number" id="iterations" step="1" value="32" min="0"> | |
<button id="rewind">«</button> | |
<button id="play">▶</button> | |
</div> | |
<div class="control"> | |
<label for="spread">spread</label> | |
<input type="checkbox" id="spread" value="1"> | |
</div> | |
<div class="control"> | |
<label for="type">Chart</label> | |
<select id="type"> | |
<option>Sankey</option> | |
<option>Sankey.Selection</option> | |
<option>Sankey.Path</option> | |
</select> | |
</div> | |
</div> | |
<div id="chart"></div> | |
<p>A Sankey diagram to fiddle with.</p> | |
<h3>Events</h3> | |
<div id="events"> | |
<div><i>Move your mouse over the chart to see events.</i></div> | |
</div> | |
<script> | |
var chart = null; | |
timer = null; | |
d3.selectAll(".controls input").on("change", updateKnobs); | |
d3.select("#source").on("change", updateSource); | |
d3.select("#type").on("change", updateType) | |
d3.select("#rewind").on("click", function() { | |
numberControl("iterations", 0); | |
}) | |
d3.select("#play").on("click", function() { | |
if (timer !== null) { | |
clearInterval(timer); timer = null; | |
} else { | |
timer = setInterval(function() { | |
numberControl("iterations", numberControl("iterations") + 1); | |
return true; | |
}, 200); | |
} | |
d3.select(this).classed("active", timer !== null); | |
}) | |
function updateKnobs() { | |
chart | |
.nodeWidth(numberControl("nodeWidth")) | |
.nodePadding(numberControl("nodePadding")) | |
.iterations(numberControl("iterations")) | |
.spread(checkControl("spread")); | |
} | |
function updateSource() { | |
d3.json(d3.select("#source").node().value, function(error, json) { | |
chart.draw(json); | |
}); | |
} | |
function updateType() { | |
var type = d3.select("#type").node().value; | |
d3.select("#chart svg").remove(); | |
chart = d3.select("#chart").append("svg").chart(type); | |
["click", "mouseover", "mouseout"].forEach(function(evt) { | |
chart.on("node:"+evt, function(node) { logEvent("node:"+evt, node.name); }); | |
chart.on("link:"+evt, function(link) { logEvent("link:"+evt, link.source.name+" → "+link.target.name); }); | |
}); | |
updateKnobs(); | |
updateSource(); | |
} | |
function numberControl(id, value) { | |
var o = d3.select("#"+id); | |
if (typeof value !== "undefined") { | |
o.node().value = String(value); | |
updateKnobs(); | |
} | |
return Number(o.node().value); | |
} | |
function checkControl(id, value) { | |
var o = d3.select("#"+id); | |
if (typeof value !== "undefined") { | |
o.node().checked = value; | |
updateKnobs(); | |
} | |
return o.node().checked; | |
} | |
function logEvent(name, s) { | |
var e = d3.select("#events"), | |
l = e.append("div"); | |
l.append("span").text(name); | |
l.append("span").text(s); | |
e.node().scrollTop = e.node().scrollHeight; | |
} | |
updateType(); | |
</script> | |
</body> | |
</html> |