Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@kunalb
Last active December 14, 2015 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kunalb/5140332 to your computer and use it in GitHub Desktop.
Save kunalb/5140332 to your computer and use it in GitHub Desktop.
<html>
<head>
<title>Cyclic Sankeys</title>
<style type="text/css">
#chart {
height: 500px;
}
.node rect {
cursor: move;
fill-opacity: .9;
shape-rendering: crispEdges;
}
.node text {
pointer-events: none;
text-shadow: 0 1px 0 #fff;
}
.linkish {
fill: #111;
stroke: #000;
opacity: .3;
}
.link:hover {
opacity: .5;
}
body {
font-size: 12px;
}
</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://raw.githubusercontent.com/kunalb/d3-plugins/sankey/sankey/sankey.js"></script>
</head>
<body>
<div id="loop"></div>
<script>
var _fillColors = d3.scale.category20();
var data1 = {
nodes: [
{name: 'A'},
{name: 'B'},
{name: 'C'},
{name: 'D'}
],
links: [
{source: 0, target: 1, value: 10},
{source: 1, target: 2, value: 10},
{source: 1, target: 0, value: 10},
{source: 2, target: 3, value: 5},
{source: 0, target: 3, value: 15},
{source: 3, target: 2, value: 5}
]
}
var data = JSON.parse('{\"nodes\":[ {\"name\":\"Agricultural \'waste\'\"}, {\"name\":\"Bio-conversion\"}, {\"name\":\"Liquid\"}, {\"name\":\"Losses\"}, {\"name\":\"Solid\"}, {\"name\":\"Gas\"}, {\"name\":\"Biofuel imports\"}, {\"name\":\"Biomass imports\"}, {\"name\":\"Coal imports\"}, {\"name\":\"Coal\"}, {\"name\":\"Coal reserves\"}, {\"name\":\"District heating\"}, {\"name\":\"Industry\"}, {\"name\":\"Heating and cooling - commercial\"}, {\"name\":\"Heating and cooling - homes\"}, {\"name\":\"Electricity grid\"}, {\"name\":\"Over generation / exports\"}, {\"name\":\"H2 conversion\"}, {\"name\":\"Road transport\"}, {\"name\":\"Agriculture\"}, {\"name\":\"Rail transport\"}, {\"name\":\"Lighting & appliances - commercial\"}, {\"name\":\"Lighting & appliances - homes\"}, {\"name\":\"Gas imports\"}, {\"name\":\"Ngas\"}, {\"name\":\"Gas reserves\"}, {\"name\":\"Thermal generation\"}, {\"name\":\"Geothermal\"}, {\"name\":\"H2\"}, {\"name\":\"Hydro\"}, {\"name\":\"International shipping\"}, {\"name\":\"Domestic aviation\"}, {\"name\":\"International aviation\"}, {\"name\":\"National navigation\"}, {\"name\":\"Marine algae\"}, {\"name\":\"Nuclear\"}, {\"name\":\"Oil imports\"}, {\"name\":\"Oil\"}, {\"name\":\"Oil reserves\"}, {\"name\":\"Other waste\"}, {\"name\":\"Pumped heat\"}, {\"name\":\"Solar PV\"}, {\"name\":\"Solar Thermal\"}, {\"name\":\"Solar\"}, {\"name\":\"Tidal\"}, {\"name\":\"UK land based bioenergy\"}, {\"name\":\"Wave\"}, {\"name\":\"Wind\"} ], \"links\":[ {\"source\":0,\"target\":1,\"value\":124.729}, {\"source\":1,\"target\":2,\"value\":0.597}, {\"source\":1,\"target\":3,\"value\":26.862}, {\"source\":1,\"target\":4,\"value\":280.322}, {\"source\":1,\"target\":5,\"value\":81.144}, {\"source\":6,\"target\":2,\"value\":35}, {\"source\":7,\"target\":4,\"value\":35}, {\"source\":8,\"target\":9,\"value\":11.606}, {\"source\":10,\"target\":9,\"value\":63.965}, {\"source\":9,\"target\":4,\"value\":75.571}, {\"source\":11,\"target\":12,\"value\":10.639}, {\"source\":11,\"target\":13,\"value\":22.505}, {\"source\":11,\"target\":14,\"value\":46.184}, {\"source\":15,\"target\":16,\"value\":104.453}, {\"source\":15,\"target\":14,\"value\":113.726}, {\"source\":15,\"target\":17,\"value\":27.14}, {\"source\":15,\"target\":12,\"value\":342.165}, {\"source\":15,\"target\":18,\"value\":37.797}, {\"source\":15,\"target\":19,\"value\":4.412}, {\"source\":15,\"target\":13,\"value\":40.858}, {\"source\":15,\"target\":3,\"value\":56.691}, {\"source\":15,\"target\":20,\"value\":7.863}, {\"source\":15,\"target\":21,\"value\":90.008}, {\"source\":15,\"target\":22,\"value\":93.494}, {\"source\":23,\"target\":24,\"value\":40.719}, {\"source\":25,\"target\":24,\"value\":82.233}, {\"source\":5,\"target\":13,\"value\":0.129}, {\"source\":5,\"target\":3,\"value\":1.401}, {\"source\":5,\"target\":26,\"value\":151.891}, {\"source\":5,\"target\":19,\"value\":2.096}, {\"source\":5,\"target\":12,\"value\":48.58}, {\"source\":27,\"target\":15,\"value\":7.013}, {\"source\":17,\"target\":28,\"value\":20.897}, {\"source\":17,\"target\":3,\"value\":6.242}, {\"source\":28,\"target\":18,\"value\":20.897}, {\"source\":29,\"target\":15,\"value\":6.995}, {\"source\":2,\"target\":12,\"value\":121.066}, {\"source\":2,\"target\":30,\"value\":128.69}, {\"source\":2,\"target\":18,\"value\":135.835}, {\"source\":2,\"target\":31,\"value\":14.458}, {\"source\":2,\"target\":32,\"value\":206.267}, {\"source\":2,\"target\":19,\"value\":3.64}, {\"source\":2,\"target\":33,\"value\":33.218}, {\"source\":2,\"target\":20,\"value\":4.413}, {\"source\":34,\"target\":1,\"value\":4.375}, {\"source\":24,\"target\":5,\"value\":122.952}, {\"source\":35,\"target\":26,\"value\":839.978}, {\"source\":36,\"target\":37,\"value\":504.287}, {\"source\":38,\"target\":37,\"value\":107.703}, {\"source\":37,\"target\":2,\"value\":611.99}, {\"source\":39,\"target\":4,\"value\":56.587}, {\"source\":39,\"target\":1,\"value\":77.81}, {\"source\":40,\"target\":14,\"value\":193.026}, {\"source\":40,\"target\":13,\"value\":70.672}, {\"source\":41,\"target\":15,\"value\":59.901}, {\"source\":42,\"target\":14,\"value\":19.263}, {\"source\":43,\"target\":42,\"value\":19.263}, {\"source\":43,\"target\":41,\"value\":59.901}, {\"source\":4,\"target\":19,\"value\":0.882}, {\"source\":4,\"target\":26,\"value\":400.12}, {\"source\":4,\"target\":12,\"value\":46.477}, {\"source\":26,\"target\":15,\"value\":525.531}, {\"source\":26,\"target\":3,\"value\":787.129}, {\"source\":26,\"target\":11,\"value\":79.329}, {\"source\":44,\"target\":15,\"value\":9.452}, {\"source\":45,\"target\":1,\"value\":182.01}, {\"source\":46,\"target\":15,\"value\":19.013}, {\"source\":47,\"target\":15,\"value\":289.366} ]}');
function createSankey(container, data) {
var nodes = data.nodes;
var links = data.links;
var width = 1200;
var height = 600;
var sankey = d3.sankey()
.size([width - 200, height - 200])
.nodeWidth(15)
.nodePadding(10)
.nodes(nodes)
.links(links)
.layout(32);
var svg = d3.select(container).append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr('transform', 'translate(' + 50 + ',' + 100 + ')');
var path = sankey.reversibleLink();
var linkEnter = svg.append("g").selectAll(".link")
.data(links)
.enter().append("g")
.attr("class", "link")
.attr("opacity", .2)
.sort(function(a, b) { return b.dy - a.dy; });
var path0 = linkEnter.append("path")
.attr("class", "link0")
.attr("fill", "none")
.attr("d", path(0))
.attr("class", "linkish");
var path1 = linkEnter.append("path")
.attr("class", "link1")
.attr("fill", "none")
.attr("d", path(1))
.attr("class", "linkish");
var path2 = linkEnter.append("path")
.attr("class", "link2")
.attr("fill", "none")
.attr("d", path(2))
.attr("class", "linkish");
linkEnter.append("title")
.text(function(d) { return d.source.name + " -> " + d.target.name; });
var node = svg.append("g").selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.call(d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", function() { this.parentNode.appendChild(this); })
.on("drag", dragmove));
node.append("rect")
.attr("height", function(d) { return d.dy; })
.attr("width", sankey.nodeWidth())
.style("fill", function(d) {
return _fillColors(d.name);
})
.style("stroke", function(d) {
return _fillColors(d.name);
})
.on("mouseover", function(d){
svg.selectAll(".link")
.filter(function(l){
return l.source == d || l.target == d;
})
.transition()
.style('opacity', .7);
})
.on("mouseout", function(d){
svg.selectAll(".link")
.filter(function(l){
return l.source == d || l.target == d;
})
.transition()
.style('opacity', .2);
})
.append("title")
.text(function(d) { return d.name; });
node.append("text")
.attr("x", -6)
.attr("y", function(d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function(d) { return d.name; })
.filter(function(d) { return d.x < width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start");
function dragmove(d) {
d3.select(this).attr("transform", "translate(" + d.x + "," + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")");
sankey.relayout();
path1.attr('d', path(1));
path0.attr('d', path(0));
path2.attr('d', path(2));
}
}
//createSankey(document.getElementById('chart'), data);
createSankey(document.getElementById('loop'), data1);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment