Chartjs-Chart.js stacked bar chart text on top of the stacked bars

1👍

The Plugin Core API offers a range of hooks that may be used for performing custom code. You can use the afterDraw hook to draw text directly on the canvas using CanvasRenderingContext2D.fillText().

chart = new Chart(ctx, {
  type: "horizontalBar",
  plugins: [{
    afterDraw: chart => {      
      var ctx = chart.chart.ctx; 
      var value =  chart.config.data.datasets[0].data[0];
      var total = chart.config.data.datasets.reduce((t, ds) => t + ds.data[0], 0);
      var percent = Math.round(1000 / total * value) / 10;
      var xAxis = chart.scales['x-axis-0'];   
      var yAxis = chart.scales['y-axis-0'];   
      ctx.save();
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.font = "24px Arial";
      ctx.fillText(value + ' (' + percent + '%) of ' + total, xAxis.right / 2, (yAxis.bottom + yAxis.top) / 2);
      ctx.restore();
    }
  }],
  ... 

Please have a look at your amended code below.

var chart;
var opts = {
  layout: {
    padding: {
      left: 0,
      right: 0,
      top: 0,
      bottom: 0
    }
  },
  responsive: true,
  maintainAspectRatio: false,
  legend: {
    display: false,
  },
  tooltips: {
    enabled: false,
  },
  scales: {
    xAxes: [{
      stacked: true,
      display: false,
      ticks: {
        fontColor: "#fff",
      }
    }, ],
    yAxes: [{
      stacked: true,
      display: false,
      ticks: {
        fontColor: "#fcafe4",
        mirror: true
      }
    }]
  }
};

var datasets = [{
    label: "My Label",
    backgroundColor: ["#FF3A2F"],
    data: [],
  },
  {
    label: "Your Label",
    backgroundColor: ["#0CB04A"],
    data: [],
  }
];

var labels = ['Label 1'];

var ctx = document.getElementById('chart-canvas');

chart = new Chart(ctx, {
  type: "horizontalBar",
  plugins: [{
    afterDraw: chart => {      
      var ctx = chart.chart.ctx; 
      var value =  chart.config.data.datasets[0].data[0];
      var total = chart.config.data.datasets.reduce((t, ds) => t + ds.data[0], 0);
      var percent = Math.round(1000 / total * value) / 10;
      var xAxis = chart.scales['x-axis-0'];   
      var yAxis = chart.scales['y-axis-0'];   
      ctx.save();
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.font = "24px Arial";
      ctx.fillText(value + ' (' + percent + '%) of ' + total, xAxis.right / 2, (yAxis.bottom + yAxis.top) / 2);
      ctx.restore();
    }
  }],
  data: {
    labels: labels,
    datasets: datasets
  },
  options: opts
});
refresh();

function refresh() {
  chart.data.datasets[0].data[0] = Math.floor(Math.random() * 1000) + 1;
  chart.data.datasets[1].data[0] = Math.floor(Math.random() * 1000) + 1;
  chart.config.options.scales.xAxes[0].ticks.max = chart.data.datasets[0].data[0] + chart.data.datasets[1].data[0];
  chart.update();
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<div class="row">
  <div class="col-lg-5 small">My Stacked Chart</div>
  <div class="col-lg-6">
    <div class="chart-container">
      <canvas id="chart-canvas"></canvas>
    </div>
  </div>
  <div class="col-lg-1 my-auto">
    <div class="btn-group">
      <button type="button" class="btn btn-primary btn-md btn-sm" onClick="refresh()">
          Refresh
      </button>
    </div>
  </div>
</div>

Leave a comment