Horizontal Stacked Bar Chart for D3.js

by Rishabh Sharma

HTML

<div id="tooltip" class="hidden">
  <p><span id="value">100</span>
  </p>
</div>

CSS

.axis path,
.axis line {
  fill: none;
  stroke: black;
  shape-rendering: crispEdges;
}

.axis text {
  font-family: sans-serif;
  font-size: 11px;
}

#tooltip {
  position: absolute;
  text-align: center;
  width: 40px;
  height: auto;
  padding: 2px 5px;
  background-color: rgba(255,255,255,0.8);
  -webkit-border-radius: 2px;
  -moz-border-radius: 2px;
  border-radius: 2px;
  -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
  -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
  box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
  pointer-events: none;
}

#tooltip.hidden {
  display: none;
}

#tooltip p {
  margin: 0;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 20px;
}

JavaScript

var margins = {
    top: 12,
    left: 64,
    right: 24,
    bottom: 24
  },
  
  legendPanel = {
    width: 180
  },
  
  width = 500 - margins.left - margins.right - legendPanel.width,
  
  height = 100 - margins.top - margins.bottom,
  
  raw = [{
      data: [{
        month: 'Last Year',
        count: 123
      }, {
        month: 'This Year',
        count: 234
      }],
      name: 'Series #1'
    }, {
      data: [{
        month: 'Last Year',
        count: 235
      }, {
        month: 'This Year',
        count: 267
      }],
      name: 'Series #2'
    }

  ],
  
  series = raw.map(function(d) {
    return d.name;
  }),
  
  dataset = raw.map(function(d) {
    return d.data.map(function(o, i) {
      // Structure it so that your numeric
      // axis (the stacked amount) is y
      return {
        y: o.count,
        x: o.month
      };
    });
  }),
  
  volumes = [0,0],
  
  stack = d3.layout.stack();
  
  raw.forEach(function(a) {
  	a.data.forEach(function(b) {
    	if(b.month === 'Last Year') {
      	volumes[0] += b.count;
      } else {
      	volumes[1] += b.count;
      }
    })
  });  
  console.log(volumes);

stack(dataset);

var dataset = dataset.map(function(group) {
    return group.map(function(d) {
      // Invert the x and y values, and y0 becomes x0
      return {
        x: d.y,
        y: d.x,
        x0: d.y0
      };
    });
  }),
  
  svg = d3.select('body')
  .append('svg')
  .attr('width', width + margins.left + margins.right + legendPanel.width)
  .attr('height', height + margins.top + margins.bottom)
  .append('g')
  .attr('transform', 'translate(' + margins.left + ',' + margins.top + ')'),
  
  xMax = d3.max(dataset, function(group) {
    return d3.max(group, function(d) {
      return d.x + d.x0;
    });
  }),
  
  xScale = d3.scale.linear()
  .domain([0, xMax])
  .range([0, width]),
  
  months = dataset[0].map(function(d) {
    return d.y;
  }),
  
  yScale = d3.scale.ordinal()
  .domain(months)
  .rangeRoundBands([0,...