Skip to content

Instantly share code, notes, and snippets.

@chriswhong
Last active January 6, 2024 02:23
Show Gist options
  • Save chriswhong/dd794c5ca90769602066 to your computer and use it in GitHub Desktop.
Save chriswhong/dd794c5ca90769602066 to your computer and use it in GitHub Desktop.
D3 Sankey Link with Variable Width

#D3 Sankey Link with Variable Width

Creates a path that resembles a sankey link, but has different heights at the source and target. I plan to use this to tie map geometries to an adjacent stacked bar chart.

<!DOCTYPE html>
<meta charset="utf-8">
<title>Variable Width Sankey Link</title>
<style>
path {
fill: steelblue;
}
</style>
<body>
<p id="chart">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
//based on 'Sankey from csv with d3.js' http://bl.ocks.org/d3noob/c9b90689c1438f57d649
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 700 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// append the svg canvas to the page
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
//array of d3 sankey nodes
var data = [{
dy: 100, //link height, same as source.dy?
source: {
dx:36, //node width
dy:40, //node height
x:0, //node position
y:125
},
sy:0, //y-offset of link from top of source node
target: {
dx:36, //node width
dy:100, //node height
x:664, //node position
y:0
},
ty: 0, //y-offset of link from top of target node
value: 2
}]
svg.selectAll("path")
.data(data)
.enter()
.append("path")
.attr("d", function(d) { return link(d)});
//borrowed from sankey.js, draws one a line from top of source to top of target, top of target to bottom of target, bottom of target to bottom of source, bottom of source to top of source
function link(d) {
var curvature = .6;
var x0 = d.source.x + d.source.dx,
x1 = d.target.x,
xi = d3.interpolateNumber(x0, x1),
x2 = xi(curvature),
x3 = xi(1 - curvature),
y0 = d.source.y + d.sy + d.dy / 2,
y1 = d.target.y + d.ty + d.dy / 2;
return "M" + x0 + "," + y0
+ "C" + x2 + "," + y0
+ " " + x3 + "," + y1
+ " " + x1 + "," + y1
+ "L" + x1 + "," + (y1+d.target.dy)
+ "C" + x3 + "," + (y1+d.target.dy)
+ " " + x2 + "," + (y0+d.source.dy)
+ " " + x0 + "," + (y0+d.source.dy)
+ "L" + x0 + "," + y0;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment