javascriptchartsgoogle-visualizationcandlestick-chartwaterfall

Annotation Google Chart API


i'm trying to use Google Chart API for building an Waterfall chart. I noticed that Candlestick/Waterfall charts are not supporting the annotations.

See this jsfiddle sample

google.charts.load('current', {'packages':['corechart']});
  google.charts.setOnLoadCallback(drawChart);
  function drawChart() {
    var data = new google.visualization.DataTable();
            data.addColumn('string', 'Category');
    data.addColumn('number', 'MinimumLevel');
    data.addColumn('number', 'MinimumLevel1');
    data.addColumn('number', 'MaximumLevel');
    data.addColumn('number', 'MaximumLevel1');
    data.addColumn({type: 'number', role: 'tooltip'});
    data.addColumn({type: 'string', role: 'style'});
    data.addColumn({type: 'number', role: 'annotation'});

    data.addRow(['Category 1', 0 , 0, 5, 5, 5,'gray',5]);
    data.addRow(['Category 2', 5 , 5, 10, 10, 10,'red',10]);
    data.addRow(['Category 3', 10 , 10, 15, 15, 15,'blue',15]);
    data.addRow(['Category 4', 15 , 15, 10, 10, 10,'yellow',10]);
    data.addRow(['Category 5', 10 , 10, 5, 5, 5,'gray',5]);

    var options = {
      legend: 'none',
      bar: { groupWidth: '60%' } // Remove space between bars.
    };

    var chart = new google.visualization.CandlestickChart(document.getElementById('chart_div'));
    chart.draw(data, options);
  }

I would like to put the value of the 5th column at the top of every candlestick. It should look like this : enter image description here

Is there a way to do this?

Thanks


Solution

  • just so happens, i ran into the same problem this week

    so I added my own annotations, during the 'animationfinish' event

    see following working snippet...

    google.charts.load('current', {
      callback: drawChart,
      packages:['corechart']
    });
    
    function drawChart() {
      var dataChart = new google.visualization.DataTable({"cols":[{"label":"Category","type":"string"},{"label":"Bottom 1","type":"number"},{"label":"Bottom 2","type":"number"},{"label":"Top 1","type":"number"},{"label":"Top 2","type":"number"},{"role":"style","type":"string","p":{"role":"style"}}],"rows":[{"c":[{"v":"Budget"},{"v":0},{"v":0},{"v":22707893.613},{"v":22707893.613},{"v":"#007fff"}]},{"c":[{"v":"Contract Labor"},{"v":22707893.613},{"v":22707893.613},{"v":22534350.429},{"v":22534350.429},{"v":"#1e8449"}]},{"c":[{"v":"Contract Non Labor"},{"v":22534350.429},{"v":22534350.429},{"v":22930956.493},{"v":22930956.493},{"v":"#922b21"}]},{"c":[{"v":"Materials and Equipment"},{"v":22930956.493},{"v":22930956.493},{"v":22800059.612},{"v":22800059.612},{"v":"#1e8449"}]},{"c":[{"v":"Other"},{"v":22800059.612},{"v":22800059.612},{"v":21993391.103},{"v":21993391.103},{"v":"#1e8449"}]},{"c":[{"v":"Labor"},{"v":21993391.103},{"v":21993391.103},{"v":21546003.177999996},{"v":21546003.177999996},{"v":"#1e8449"}]},{"c":[{"v":"Travel"},{"v":21546003.177999996},{"v":21546003.177999996},{"v":21533258.930999994},{"v":21533258.930999994},{"v":"#1e8449"}]},{"c":[{"v":"Training"},{"v":21533258.930999994},{"v":21533258.930999994},{"v":21550964.529999994},{"v":21550964.529999994},{"v":"#922b21"}]},{"c":[{"v":"Actual"},{"v":0},{"v":0},{"v":21550964.52999999},{"v":21550964.52999999},{"v":"#007fff"}]}]});
    
      var waterFallChart = new google.visualization.ChartWrapper({
        chartType: 'CandlestickChart',
        containerId: 'chart_div',
        dataTable: dataChart,
        options: {
          animation: {
            duration: 1500,
            easing: 'inAndOut',
            startup: true
          },
          backgroundColor: 'transparent',
          bar: {
            groupWidth: '85%'
          },
          chartArea: {
            backgroundColor: 'transparent',
            height: 210,
            left: 60,
            top: 24,
            width: '100%'
          },
          hAxis: {
            slantedText: false,
            textStyle: {
              color: '#616161',
              fontSize: 9
            }
          },
          height: 272,
          legend: 'none',
          tooltip: {
            isHtml: true,
            trigger: 'both'
          },
          vAxis: {
            format: 'short',
            gridlines: {
              count: -1
            },
            textStyle: {
              color: '#616161'
            },
            viewWindow: {
              max: 24000000,
              min: 16000000
            }
          },
          width: '100%'
        }
      });
    
      google.visualization.events.addOneTimeListener(waterFallChart, 'ready', function () {
        google.visualization.events.addListener(waterFallChart.getChart(), 'animationfinish', function () {
          var annotation;
          var chartLayout;
          var container;
          var numberFormatShort;
          var positionY;
          var positionX;
          var rowBalance;
          var rowBottom;
          var rowFormattedValue;
          var rowIndex;
          var rowTop;
          var rowValue;
          var rowWidth;
    
          container = document.getElementById(waterFallChart.getContainerId());
          chartLayout = waterFallChart.getChart().getChartLayoutInterface();
          numberFormatShort = new google.visualization.NumberFormat({
            pattern: 'short'
          });
          rowIndex = 0;
          Array.prototype.forEach.call(container.getElementsByTagName('rect'), function(rect) {
            switch (rect.getAttribute('fill')) {
              // use colors to identify bars
              case '#922b21':
              case '#1e8449':
              case '#007fff':
                rowWidth = parseFloat(rect.getAttribute('width'));
                if (rowWidth > 2) {
                  rowBottom = waterFallChart.getDataTable().getValue(rowIndex, 1);
                  rowTop = waterFallChart.getDataTable().getValue(rowIndex, 3);
                  rowValue = rowTop - rowBottom;
                  rowBalance = Math.max(rowBottom, rowTop);
                  positionY = chartLayout.getYLocation(rowBalance) - 6;
                  positionX = parseFloat(rect.getAttribute('x'));
                  rowFormattedValue = numberFormatShort.formatValue(rowValue);
                  if (rowValue < 0) {
                    rowFormattedValue = rowFormattedValue.replace('-', '');
                    rowFormattedValue = '(' + rowFormattedValue + ')';
                  }
                  annotation = container.getElementsByTagName('svg')[0].appendChild(container.getElementsByTagName('text')[0].cloneNode(true));
                  $(annotation).text(rowFormattedValue);
                  annotation.setAttribute('x', (positionX + (rowWidth / 2)));
                  annotation.setAttribute('y', positionY);
                  annotation.setAttribute('font-weight', 'bold');
                  rowIndex++;
                }
                break;
            }
          });
        });
      });
    
      $(window).resize(function() {
        waterFallChart.draw();
      });
      waterFallChart.draw();
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="chart_div"></div>