Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3js stack chart with simple data

I need a very basic example to create a stack chart like this example with a predefined array like this:

var data = [[ 1,  4,  2,  7],
            [21,  2,  5, 10],
            [ 1, 17, 16,  6]]

Whatever I do ends creating errors. E.g. TypeError: data is undefined. Here is my simplified code so far:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v2.js?2.9.5"></script>
<script>

var margin = {top: 20, right: 30, bottom: 30, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var data = [[ 1,  4,  2,  7],
            [21,  2,  5, 10],
            [ 1, 17, 16,  6]];

var x = d3.scale.linear()
    .range([0, width])
    .domain([0,3]);

var y = d3.scale.linear()
    .range([height, 0])
    .domain([0,25]);

var z = d3.scale.category20c();

var svg = d3.select("body").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 + ")");

var stack = d3.layout.stack(data)
      .offset("zero")
      .values(function(d) { return d; })
      .x(function(d, i) { return i; })
      .y(function(d) { return d; });

var area = d3.svg.area()
    .x(function(d, i) { return x(i); })
    .y0(function(d) { return y(d.y0); })
    .y1(function(d) { return y(d.y0 + d.y); });

svg.selectAll(".layer")
      .data(stack)
      .enter().append("path")
      .attr("class", "layer")
      .attr("d", function(d) { return area(d.values); })
      .style("fill", function(d, i) { return colors[i]; });

</script>
like image 810
Fabian Avatar asked Jan 29 '26 01:01

Fabian


1 Answers

You can see a working example at http://jsfiddle.net/DyrsK/2/.

Generally I find it easier to permute the input data a little bit to get into the default form that d3 expects. For this example I took your data and computed the x, y and y0 values and then passed that to the default stack layout.

var data = [[ 1,  4,  2,  7],
            [21,  2,  5, 10],
            [ 1, 17, 16,  6]];

// permute the data
data = data.map(function(d) { 
    return d.map(function(p, i) { 
        return {x:i, y:p, y0:0};
    });
});

I think there is an easier way to do this, but I had trouble with the out() function of d3.layout.stack() since your input data was a value but the out() function expects it to be a reference value. This meant that there wasn't a way to update the values with the computed offsets and so the data being returned by stack() was always equal to the input values.

After getting the stack function to work, the rest pretty much followed from the example you linked to:

var stack = d3.layout.stack()
      .offset("zero")

var layers = stack(data);

var area = d3.svg.area()
    .interpolate('cardinal')
    .x(function(d, i) { return x(i); })
    .y0(function(d) { return y(d.y0); })
    .y1(function(d) { return y(d.y0 + d.y); });

svg.selectAll(".layer")
      .data(layers)
      .enter().append("path")
      .attr("class", "layer")
      .attr("d", function(d) { return area(d); })
      .style("fill", function(d, i) { return colors(i); });

Hope this helps!

like image 69
Bill Avatar answered Jan 31 '26 20:01

Bill



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!