Stacked and grouped bar chart

by christopheviau

HTML

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

CSS

rect{
    fill:skyblue;
    stroke:aliceblue;
}

JavaScript

var data = d3.range(10).map(Math.random),
    chartW = 300, 
    chartH = 200, 
    margin = [10, 10, 10, 10], 
    gap = 10;

//var barChart = computeBarchart(data, 0, 0, chartW, chartH, margin, gap);
var barChart = computeStackedBarchart(data, 0, 0, chartW, chartH, margin, gap);

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