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> |