[Chartjs]-Can I offset the bars in chart.js stacked bar chart?

3👍

Based on this answer, I created a runnable code snippet that illustrates how it could be done. I’m not using stacked bars because the use case is not clear to me and the image from the question rather looks like a bar with shadows.

const dataset = [40, 80, 50, 60, 70];
const offset = 8;

Chart.pluginService.register({
    afterUpdate: function(chart) {
        var dataset = chart.config.data.datasets[1];
        for (var i = 0; i < dataset._meta[0].data.length; i++) {
            var model = dataset._meta[0].data[i]._model;
            model.x += offset;
            model.controlPointNextX += offset;
            model.controlPointPreviousX += offset;
        }
    }
});

var data = {
    labels: ["A", "B", "C", "D", "E"],
    datasets: [{
            backgroundColor: [
              'rgba(255, 99, 132)',
              'rgba(255, 206, 86)',
              'rgba(54, 162, 235)',              
              'rgba(75, 192, 192)',
              'rgba(153, 102, 255)'
              ],
            borderWidth: 1,
            data: dataset,
            xAxisID: "bar-x-axis1",
            categoryPercentage: 0.5,
            barPercentage: 0.5,
        },
        {
            backgroundColor: 'rgba(0, 0, 0, 0.2)',
            data: dataset.map(v => v + offset),
            xAxisID: "bar-x-axis2",
            categoryPercentage: 0.5,
            barPercentage: 0.5
        }
    ]
};

var options = {  
    legend: {
        display: false
    },
    tooltips: {
        enabled: false
    },
    scales: {        
        xAxes: [
            {
                id: "bar-x-axis2"
            },
            {
                id: "bar-x-axis1",              
                offset: true,
                ticks: {
                   display: false
                }
           }
        ],
        yAxes: [{
            id: "bar-y-axis1",
            ticks: {
                beginAtZero: true,
                stepSize: 50
            }
        }]
    }
};

var ctx = document.getElementById("myChart").getContext("2d");
var myBarChart = new Chart(ctx, {
    type: 'bar',
    data: data,
    options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="60"></canvas>

1👍

For Chart.js v3, you can use a different approach.

  1. In the beforeDatasetsDraw, you save the define the shadow properties on the canvas through CanvasRenderingContext2D. Make sure to first save the state of the rendering context by invoking ctx.save().
  2. In the afterDatasetsDraw hook, you need to restore the state of the rendering context by invoking ctx.restore().
  3. Convert the bars into floating bars through data: data.map(v => [-20, v]) to makes sure, the shadows appear from the base of the bars.
  4. Define a tooltip.callbacks.label function that provides the initial values in the tooltips.

Please take a look at below runnable code and see how it works.

const data = [40, 80, 50, 60, 70];
const offset = 10;

new Chart('myChart', {
  type: 'bar',
  plugins: [{
    beforeDatasetsDraw: chart => {
      const ctx = chart.ctx;
      ctx.save();
      ctx.shadowOffsetX = offset;
      ctx.shadowOffsetY = -offset;
      ctx.shadowBlur = 5;
      ctx.shadowColor = 'rgb(220, 220, 220)';
    },
    afterDatasetsDraw: chart => chart.ctx.restore()
  }],
  data: {
    labels: ["A", "B", "C", "D", "E"],
    datasets: [{
      label: 'My Data',
      data: data.map(v => [-20, v]),
      backgroundColor: [
        'rgba(255, 99, 132)',
        'rgba(255, 206, 86)',
        'rgba(54, 162, 235)',
        'rgba(75, 192, 192)',
        'rgba(153, 102, 255)'
      ],
      categoryPercentage: 0.8
    }]
  },
  options: {
    plugins: {
      tooltip: {
        callbacks: {
          label: ctx => data[ctx.dataIndex]
        }
      }
    },
    scales: {
      y: {
        min: 0,
        max: Math.max(...data) + offset
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>

Leave a comment