Chartjs-Data label over stacked bar chart

0👍

This can be done using the following options:

animation:
{
  onComplete: function()
  {
    var chartInstance = this.chart;
    var horizontal = chartInstance.config.type.lastIndexOf("horizontal", 0) === 0; //if type of graph starts with horizontal

    var ctx = chartInstance.ctx;
    ctx.textAlign = (horizontal) ? "left" : "center";
    ctx.textBaseline = (horizontal) ? "middle" : "bottom";
    ctx.font = '16px "Helvetica Neue", Helvetica, Arial, sans-serif';
    ctx.fillStyle = "#000";

    var dataLabels = {}; //key = x or y coordinate (depends on grouping), value = Array[0] other coordinate , Array[1] = value to print
    var equationForGrouping = (horizontal) ? Math.max : Math.min; //equation to use for grouping

    //get values from chart, fill them in dataLabels (as seen in https://github.com/chartjs/Chart.js/blob/master/samples/data_label_combo-bar-line.html )
    Chart.helpers.each(this.data.datasets.forEach(function(dataset, i)
    {
      var meta = chartInstance.controller.getDatasetMeta(i);
      Chart.helpers.each(meta.data.forEach(function(bar, index)
      { //for each part of each stacked bar
        if(meta.hidden != true) //if data is not hidden (by clicking on it in the legend)
        {
          var groupByCoordinate = (horizontal) ? bar._model.y : bar._model.x;
          var otherCoordinate = (horizontal) ? bar._model.x : bar._model.y;

          if(dataLabels[groupByCoordinate])
          {
            dataLabels[groupByCoordinate][0] = equationForGrouping(otherCoordinate, dataLabels[groupByCoordinate][0]);
            dataLabels[groupByCoordinate][1] += dataset.data[index];
          }
          else
            dataLabels[groupByCoordinate] = [otherCoordinate, dataset.data[index]];
          }
        }), this)
      }), this);

      //draw values onto graph
      for(var key in dataLabels)
      {
        if(dataLabels[key][1] >= 1000000) //million
          dataLabels[key][1] = Math.round(dataLabels[key][1] / 1000000) + "m";
        else if(dataLabels[key][1] >= 1000) //thousand
          dataLabels[key][1] = Math.round(dataLabels[key][1] / 1000) + "k";

        if(horizontal) //if grouped by y values
          ctx.fillText(dataLabels[key][1], dataLabels[key][0], key);
        else
          ctx.fillText(dataLabels[key][1], key, dataLabels[key][0]);
      }
    }
  }
};

See this example: https://jsfiddle.net/s4r2rj8h/1

example

Leave a comment