D3JS stacked bar chart with Negative values

by Rishabh Sharma

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<div ng-controller="MyCtrl as vm">
  <line-chart data="vm.data"></line-chart>
</div>

CSS

.axis text {
  font: 10px sans-serif;
}

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

JavaScript

angular.module('myApp', [])
  .controller('MyCtrl', function($scope) {
    this.data = [{
      "Month": "Jan",
      "P": 310504,
      "I": 552339,
      "D": 259034
    }, {
      "Month": "Feb",
      "P": 52083,
      "I": 85640,
      "D": 42153
    }, {
      "Month": "Mar",
      "P": 515910,
      "I": 828669,
      "D": 362642
    }, {
      "Month": "Apr",
      "P": 202070,
      "I": 343207,
      "D": 157204
    }, {
      "Month": "May",
      "P": 2704659,
      "I": 4499890,
      "D": 2159981
    }, {
      "Month": "Jun",
      "P": 358280,
      "I": 587154,
      "D": 261701
    }, {
      "Month": "Jul",
      "P": 211637,
      "I": 403658,
      "D": 196918
    }, {
      "Month": "Aug",
      "P": 59319,
      "I": 99496,
      "D": 47414
    }];
  })
  .directive('lineChart', function($window) {
    return {
      restrict: 'E',
      replace: true,
      scope: {
        data: '='
      },
      template: '<div class="stacked-bar-chart"></div>',
      link: function(scope, element, attrs, fn) {

        var d3 = $window.d3;
        /* 
	an iteration on this bl.ock
	http://bl.ocks.org/ZJONSSON/2975320 
	barStack - stacking with negative values
*/

        function barStack(seriesData) {
          var l = seriesData[0].length
          while (l--) {
            var posBase = 0; // positive base
            var negBase = 0; // negative base

            seriesData.forEach(function(d) {
              d = d[l]
              d.size = Math.abs(d.y)
              if (d.y < 0) {
                d.y0 = negBase
                negBase -= d.size
              } else {
                d.y0 = posBase = posBase + d.size
              }
            })
          }
          seriesData.extent = d3.extent(
            d3.merge(
              d3.merge(
                seriesData.map(function(e) {
                  return e.map(function(f) {
                    return [f.y0, f.y0 - f.size]
                  })
                })
              )
           ...