2

I'm trying to create a stack bar graph using the stack layout.

I can make it work only if I pass it an array of x,y coordinates. But I want to be able to add meta data to it, such as series title.

I've read the docs (https://github.com/mbostock/d3/wiki/Stack-Layout), and seen how it's done on a steamgraph (Correct usage of stack.values([accessor]) in D3 Streamgraph?). The problem with these examples is that they don't take into account things like y scale, making it difficult to establish variables such as yStackMax.

I also need the data to be passed to the stack() function early on, because I'm planning to redraw this and other things when the data is refreshed. In short, instead of:

var data = [
   [
      { "x": 0, "y":  91},
      { "x": 1, "y": 290}
   ],
  [
      { "x": 0, "y":  9},
      { "x": 1, "y": 49}
   ],
   [
      { "x": 0, "y": 10},
      { "x": 1, "y": 25}
    ]
];


var layers = d3.layout.stack()(data);

var yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });

... which works, I want to be able to do:

var data = [
  {
    "name": "apples",
    "values": [
      { "x": 0, "y":  91},
      { "x": 1, "y": 290}
    ]
  },
  {  
    "name": "oranges",
    "values": [
      { "x": 0, "y":  9},
      { "x": 1, "y": 49}
    ]
  },
  {  
    "name": "potatoes",
    "values": [
      { "x": 0, "y": 10},
      { "x": 1, "y": 25}
    ]
  }
];

var layers = d3.layout.stack()(data).values(function(d) { return d.values; });

var yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });

... which doesn't work.

This is the working code fiddle: http://jsfiddle.net/StephanTual/E6FeP/

This is the fiddle for the code that doesn't work: http://jsfiddle.net/StephanTual/Tnj8W/

Community
  • 1
  • 1
Stephan Tual
  • 2,617
  • 3
  • 27
  • 49

1 Answers1

4

Here's an updated fiddle.

The key part was:

// define the accessor before adding in the data
var layers = d3.layout.stack().values(function(d) { return d.values; })(data);

var yStackMax = d3.max(layers, function(layer) { return d3.max(layer.values, function(d) { return d.y0 + d.y; }); });

And then I made a couple other adjustments as necessary to access the .values.

kalley
  • 18,072
  • 2
  • 39
  • 36
  • Thank you Kalley. This works wonders, amazing stuff. Do you know by any chance if it's possible to provide the data with missing elements, so that the graph doesn't try to render things where y=0 ? I'm asking this in regards to performance, as rendering 10+ series over just a hundred data points creates a rendering bottleneck. – Stephan Tual Aug 06 '13 at 14:26
  • Have you tried filtering the data? I don't know if there is a built in way to do that, but I'll gladly take a look. You might want to ask another question. :) – kalley Aug 06 '13 at 15:10