Stacked and grouped bar chart

Uses d3.layout.stack, d3.scale, computes (x, y, w, h), single column for now, data transform

by christopheviau

HTML

<script src="http://mbostock.github.com/d3/d3.js"></script>

CSS

rect{
    fill:skyblue;
    stroke:blue;
}

JavaScript

//var data = d3.range(2).map(function(){return d3.range(3).map(Math.random)}),
var data = [[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]],
    chartW = 300, 
    chartH = 200, 
    margin = [10, 10, 10, 10], 
    gap = 10;

var dataForStack = data.map(function(d, i){return d.map(function(d2, i2){return {x: i2, y: d2};});});

var stackedData = d3.layout.stack().offset('zero')(dataForStack); //silhouette, wiggle, expand, zero

var dataTmp = d3.transpose(stackedData)[0];

//var barChart = computeBarchart(dataTmp, 0, 0, chartW, chartH, margin, gap);
var barChart = computeStackedBarchart(dataTmp, 0, 0, chartW, chartH, margin, gap);
                                      
d3.select("body")
    .append("svg")
    .attr("width", chartW+20)
    .attr("height", chartH+20)
    .selectAll("rect")
    .data(dataTmp)
    .enter().append("rect")
    .attr("width", barChart.w)
    .attr("height", barChart.h)
    .attr("x", barChart.x)
    .attr("y", barChart.y);
  
/*===========================================================*/
    
function computeStackedBarchart(data, chartX, chartY, chartW, chartH, margin, gap){
    var dataY = data.map(function(d, i){return d.y;});  
    
    var yScale = d3.scale.linear().domain([0, d3.sum(dataY)]).range([0,chartH]);            
    var gapW = chartW*(gap/100);
    
    var markX = function(d, i){return chartX+margin[3]+gapW/2;};
    var markY = function(d, i){return chartH-yScale(d.y)-yScale(d.y0)+margin[0];};
    var markW = function(d, i){return chartW-gapW;};
    var markH = function(d, i){return yScale(d.y);};
    return {x: markX, y: markY, w: markW, h: markH};
};

function computeBarchart(data, chartX, chartY, chartW, chartH, margin, gap){
    var dataY = data.map(function(d, i){return d.y;});
    
    var yScale = d3.scale.linear().domain([0, d3.max(dataY)]).range([0,chartH]);            
    var gapW = chartW*(gap/100);
    
    var markW = chartW/dataTmp.length-gapW;
    var markH = function(d, i){return yScale(d.y);};
    var markX =...