Streamgraph

Streamgraph algorithm, colors, and data generation inspired by Byron and Wattenberg.

Source Code

 1 var n = 20, // number of layers
 2     m = 200, // number of samples per layer
 3     data0 = d3.layout.stack().offset("wiggle")(stream_layers(n, m)),
 4     data1 = d3.layout.stack().offset("wiggle")(stream_layers(n, m)),
 5     color = d3.interpolateRgb("#aad", "#556");
 6 
 7 var w = 960,
 8     h = 500,
 9     mx = m - 1,
10     my = d3.max(data0.concat(data1), function(d) {
11       return d3.max(d, function(d) {
12         return d.y0 + d.y;
13       });
14     });
15 
16 var area = d3.svg.area()
17     .x(function(d) { return d.x * w / mx; })
18     .y0(function(d) { return h - d.y0 * h / my; })
19     .y1(function(d) { return h - (d.y + d.y0) * h / my; });
20 
21 var vis = d3.select("#chart")
22   .append("svg:svg")
23     .attr("width", w)
24     .attr("height", h);
25 
26 vis.selectAll("path")
27     .data(data0)
28   .enter().append("svg:path")
29     .style("fill", function() { return color(Math.random()); })
30     .attr("d", area);
31 
32 function transition() {
33   d3.selectAll("path")
34       .data(function() {
35         var d = data1;
36         data1 = data0;
37         return data0 = d;
38       })
39     .transition()
40       .duration(2500)
41       .attr("d", area);
42 }
 1 /* Inspired by Lee Byron's test data generator. */
 2 function stream_layers(n, m, o) {
 3   if (arguments.length < 3) o = 0;
 4   function bump(a) {
 5     var x = 1 / (.1 + Math.random()),
 6         y = 2 * Math.random() - .5,
 7         z = 10 / (.1 + Math.random());
 8     for (var i = 0; i < m; i++) {
 9       var w = (i / m - y) * z;
10       a[i] += x * Math.exp(-w * w);
11     }
12   }
13   return d3.range(n).map(function() {
14       var a = [], i;
15       for (i = 0; i < m; i++) a[i] = o + o * Math.random();
16       for (i = 0; i < 5; i++) bump(a);
17       return a.map(stream_index);
18     });
19 }
20 
21 /* Another layer generator using gamma distributions. */
22 function stream_waves(n, m) {
23   return d3.range(n).map(function(i) {
24     return d3.range(m).map(function(j) {
25         var x = 20 * j / m - i / 3;
26         return 2 * x * Math.exp(-.5 * x);
27       }).map(stream_index);
28     });
29 }
30 
31 function stream_index(d, i) {
32   return {x: i, y: Math.max(0, d)};
33 }
Copyright © 2011 Mike Bostock
Fork me on GitHub