Waterfall Chart

by Rishabh Sharma

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div ng-controller="MyCtrl">
  <div>
    <select ng-model="selectData">
      <option value="data1">data 1</option>
      <option value="data2">data 2</option>
      <option value="data3">data 3</option>
    </select>
  </div>
  <div>
    {{selectData}}
    <waterfall chart-data="chartData" select-data="selectData"></waterfall>
  </div>
</div>

CSS

.bar line.connector {
  stroke: black;
  stroke-dasharray: 3;
}

.bar text {
  fill: white;
  font: 12px sans-serif;
  text-anchor: middle;
}

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

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

JavaScript

var myApp = angular.module('myApp', []);

myApp.controller('MyCtrl', function($scope) {

  $scope.selectData = "data2";

  $scope.chartData = {
    data1: [{
      id: 1,
      name: "LY",
      value: 2000000
    }, {
      id: 2,
      name: "P",
      value: 100000
    }, {
      id: 3,
      name: "I",
      value: -200000
    }, {
      id: 4,
      name: "D",
      value: -500000
    }],
    data2: [{
      id: 1,
      name: "LY",
      value: 3000000
    }, {
      id: 2,
      name: "P",
      value: -1000000
    }, {
      id: 3,
      name: "I",
      value: 500000
    }, {
      id: 4,
      name: "D",
      value: -300000
    }],
    data3: [{
      id: 1,
      name: "LY",
      value: 1000000
    }, {
      id: 2,
      name: "P",
      value: 2000000
    }, {
      id: 3,
      name: "I",
      value: 500000
    }, {
      id: 4,
      name: "D",
      value: 2000000
    }]
  };

});

myApp.directive('waterfall', function() {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      chartData: '=',
      selectData: '='
    },
    template: "<svg class='waterfall-chart'></svg>",
    link: function(scope, element, attrs, fn) {

      var rawSvg = element;

      var data = scope.chartData.data1;

      scope.$watch('selectData', function(newValue, oldValue) {
        console.log(newValue);
        if (newValue === "data1") {
          data = scope.chartData.data1;
        } else if (newValue === "data2") {
          data = scope.chartData.data2;
        } else {
          data = scope.chartData.data3;
        }

        paintChart();
      });

      var margin = {
          top: 100,
          right: 0,
          bottom: 0,
          left: -70
        },
        width = 500 - margin.left - margin.right,
        height = 220 - margin.top - margin.bottom,
        padding = 0.80;

      var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], padding);

      var y = d3.scale.linear()
        .range([height, 0]);

      /*           ...