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]
})
})
)
...