Skip to content

Instantly share code, notes, and snippets.

@bencekd
Last active July 27, 2016 09:27
Show Gist options
  • Save bencekd/6e3bfdb42b23d6ec5b7091853c6cfc59 to your computer and use it in GitHub Desktop.
Save bencekd/6e3bfdb42b23d6ec5b7091853c6cfc59 to your computer and use it in GitHub Desktop.
Streamgraph_example
license: gpl-3.0

For continuous data such as time series, a streamgraph can be used in place of stacked bars. This example also demonstrates path transitions to interpolate between different layouts. Streamgraph algorithm, colors, and data generation inspired by Byron and Wattenberg.

forked from mbostock's block: Streamgraph

<!DOCTYPE html>
<meta charset="utf-8">
<title>Streamgraph</title>
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
position: relative;
width: 960px;
}
button {
position: absolute;
right: 10px;
top: 10px;
}
</style>
<button onclick="transition()">Update</button>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var n = 8, // number of layers
m = 200, // number of samples per layer
stack = d3.layout.stack().offset("wiggle"),
layers0 = stack(d3.range(n).map(function() { return bumpLayer(m); })),
layers1 = stack(d3.range(n).map(function() { return bumpLayer(m); }));
var width = 960,
height = 500;
var x = d3.scale.linear()
.domain([0, m - 1])
.range([0, width]);
console.log("debug");
console.log(layers1[1][0].x);
var y = d3.scale.linear()
.domain([0, d3.max(layers0.concat(layers1), function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); })])
.range([height, 0]);
var color = d3.scale.linear()
.domain([0, 0.5, 1])
.range(["#1446A0", "#DB3069", "#F5D547"]);
var area = d3.svg.area()
.x(function(d) { return x(d.x); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.selectAll("path")
.data(layers0)
.enter().append("path")
.attr("d", area)
.style("fill", function() { return color(Math.random()); });
var text = svg.selectAll("text")
.data(layers0)
.enter()
.append("text");
console.log(layers1);
for(i=0;i<m-1;i++){
text
.transition()
.duration(300)
.delay(1000*i)
.attr("x", function(d) { console.log("at least"); return x(d[i].x); })
.attr("y", function(d) { return y(d[i].y0 + d[i].y); })
.text( function (d) {console.log("debug here");
console.log(d);
return "(x: " + parseInt(x(d[i].x)) + ", y:" +
parseInt(y(d[i].y)-parseInt(y(d[i].y0))) +" )";
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "black");
}
function transition() {
d3.selectAll("path")
.data(function() {
var d = layers1;
layers1 = layers0;
return layers0 = d;
})
.transition()
.duration(2500)
.attr("d", area);
}
// Inspired by Lee Byron's test data generator.
function bumpLayer(n) {
function bump(a) {
var x = 1 / (.1 + Math.random()),
y = 2 * Math.random() - .5,
z = 10 / (.1 + Math.random());
for (var i = 0; i < n; i++) {
var w = (i / n - y) * z;
a[i] += x * Math.exp(-w * w);
}
}
var a = [], i;
for (i = 0; i < n; ++i) a[i] = 0;
for (i = 0; i < 5; ++i) bump(a);
return a.map(function(d, i) { return {x: i, y: Math.max(0, d)}; });
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment