'Can I offset the bars in chart.js stacked bar chart?

Can I offset the bars in the chart.js stacked bar chart like so: enter image description here



Solution 1:[1]

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>

Solution 2:[2]

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>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 uminder
Solution 2 uminder