Chart.js With a mixed chart (step and bar chart), how do I get each step to start at the beginning of the bar instead of the middle the stacked bar?

Viewed 79

I tried to remove the offset for the bar chart (offset: false), but the result has the first bar shifted to the left such that only half of the first bar is shown. Here is what I have but the beginning and end of the step chart are not showing.

function createBarChart() {
        const ctx = document.getElementById('myChart');
        const myChart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: ['1', '2', '3', '4', '5', '6'],
                datasets: [
                    {
                        type: 'line',
                        label: 'Dataset 1',
                        data: [18, 19, 16, 12, 13, 11],
                        borderColor: 'rgb(54, 162, 235)',
                        fill: false,
                        radius: 0,
                        stepped: 'middle',
                        // xAxisID: 'xStepChart'
                    },
                    {
                        type: 'bar',
                        label: 'Label 2',
                        data: [9.35, 8.35, 8.56, 6.46, 5.04, 3.15],
                        //-- No gaps between bars
                        barPercentage: 1.0,
                        categoryPercentage: 1.0,
                        backgroundColor: ['#71797E'],
                        borderColor: ['#000000'],
                        borderWidth: 1
                    },
                    {
                        type: 'bar',
                        label: 'Label 3',
                        data: [20.34, 17.31, 16.39, 13.48, 11.29, 11.23],
                        //-- No gaps between bars
                        barPercentage: 1.0,
                        categoryPercentage: 1.0,
                        backgroundColor: ['#A9A9A9'],
                        borderColor: ['#000000'],
                        borderWidth: 1
                    },
                    {
                        type: 'bar',
                        label: 'Label 4',
                        data: [20.40, 18.57, 16.96, 14.19, 12.68, 11.98],
                        //-- No gaps between bars
                        barPercentage: 1.0,
                        categoryPercentage: 1.0,
                        backgroundColor: ['rgba(46, 142, 201, 0.2)'],
                        borderColor: ['rgba(61, 61, 60, 1)'],
                        borderWidth: 1
                    },
                ]
            },
            options: {
                scales: {
                    x: {
                        stacked: true,
                    },
                    y: {
                        stacked: false
                    }   
                }
            }
        })
    }

enter image description here

1 Answers

You can define the 'line' data as an array of points (individual objects having an x and y property each). Then tie the dataset to a second non-displayed x-axis.

{
  type: 'line',
  label: 'Dataset 1',
  data: [{x: 0, y: 18}, {x: 1, y: 19}, {x: 2, y: 16}, {x: 3, y: 12}, {x: 4, y: 13}, {x: 5, y: 11}, {x: 6, y: 11}],
  ...
  stepped: 'end',
  xAxisID: 'x2'
},

The x-axis for the 'line' dataset...

x2: {
  type: 'linear',
  display: false        
}

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

new Chart('myChart', {
  type: 'line',
  data: {
    labels: ['1', '2', '3', '4', '5', '6'],
    datasets: [{
        type: 'line',
        label: 'Dataset 1',
        data: [{x: 0, y: 18}, {x: 1, y: 19}, {x: 2, y: 16}, {x: 3, y: 12}, {x: 4, y: 13}, {x: 5, y: 11}, {x: 6, y: 11}],
        borderColor: 'rgb(54, 162, 235)',
        fill: false,
        radius: 0,
        stepped: 'end',
        xAxisID: 'x2'
      },
      {
        type: 'bar',
        label: 'Label 2',
        data: [9.35, 8.35, 8.56, 6.46, 5.04, 3.15],
        //-- No gaps between bars
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        backgroundColor: ['#71797E'],
        borderColor: ['#000000'],
        borderWidth: 1
      },
      {
        type: 'bar',
        label: 'Label 3',
        data: [20.34, 17.31, 16.39, 13.48, 11.29, 11.23],
        //-- No gaps between bars
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        backgroundColor: ['#A9A9A9'],
        borderColor: ['#000000'],
        borderWidth: 1
      },
      {
        type: 'bar',
        label: 'Label 4',
        data: [20.40, 18.57, 16.96, 14.19, 12.68, 11.98],
        //-- No gaps between bars
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        backgroundColor: ['rgba(46, 142, 201, 0.2)'],
        borderColor: ['rgba(61, 61, 60, 1)'],
        borderWidth: 1
      },
    ]
  },
  options: {
    scales: {
      x: {
        stacked: true,
      },
      x2: {
        type: 'linear',
        display: false        
      },
      y: {
        stacked: false
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<canvas id="myChart"></canvas>

In case you have more data points, you may also have to define x2.max in order to keep the datasets synchronized (show code snippet below).

new Chart('myChart', {
  type: 'line',
  data: {
    labels: [
          '1', '2', '3', '4', '5', '6',
          '7',  '8',  '9', '10', '11', '12',
         '13', '14', '15', '16', '17', '18',
         '19', '20', '21', '22', '23', '24'
        ],
    datasets: [{
        type: 'line',
        label: 'Dataset 1',
        data: [
            {x: 0, y: 18}, {x: 1, y: 19}, {x: 2, y: 16}, {x: 3, y: 12}, {x: 4, y: 13}, {x: 5, y: 11}, 
            {x: 6, y:  9.37}, {x: 7, y:  9.28}, {x: 8, y: 11.90}, {x: 9, y: 19.00}, {x: 10, y: 18.50}, {x: 11, y: 21.00},
            {x: 12, y: 24.98}, {x: 13, y: 22.12}, {x: 14, y: 21.73}, {x: 15, y: 23.50}, {x: 16, y: 27.50}, {x: 17, y: 26.00},
            {x: 18, y: 23.51}, {x: 19, y: 22.50}, {x: 20, y: 23.40}, {x: 21, y: 22.50}, {x: 22, y: 22.55}, {x: 23, y: 24.11},
            {x: 24, y: 24.11}
            ],
        borderColor: 'rgb(54, 162, 235)',
        fill: false,
        radius: 0,
        stepped: 'end',
        xAxisID: 'x2'
      },
      {
        type: 'bar',
        label: 'Label 2',
        data: [
            9.35, 8.35, 8.56, 6.46, 5.04, 3.15,
            2.45, 3.05, 4.53, 6.52, 7.64, 8.62,
            9.53, 9.41, 10.17, 10.64, 11.62, 11.30,
            9.48, 11.08, 10.84, 10.08, 11.05, 9.94
          ],
        //-- No gaps between bars
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        backgroundColor: ['#71797E'],
        borderColor: ['#000000'],
        borderWidth: 1
      },
      {
        type: 'bar',
        label: 'Label 3',
        data: [
            20.34, 17.31, 16.39, 13.48, 11.29, 11.23,
            20.34, 17.31, 16.39, 13.48, 11.29, 11.23,
            20.34, 17.31, 16.39, 13.48, 11.29, 11.23,
            20.34, 17.31, 16.39, 13.48, 11.29, 11.23
          ],
        //-- No gaps between bars
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        backgroundColor: ['#A9A9A9'],
        borderColor: ['#000000'],
        borderWidth: 1
      },
      {
        type: 'bar',
        label: 'Label 4',
        data: [
            20.40, 18.57, 16.96, 14.19, 12.68, 11.98,
            20.40, 18.57, 16.96, 14.19, 12.68, 11.98,
            20.40, 18.57, 16.96, 14.19, 12.68, 11.98,
            20.40, 18.57, 16.96, 14.19, 12.68, 11.98
          ],
        //-- No gaps between bars
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        backgroundColor: ['rgba(46, 142, 201, 0.2)'],
        borderColor: ['rgba(61, 61, 60, 1)'],
        borderWidth: 1
      },
    ]
  },
  options: {
    scales: {
      x: {
        stacked: true,
      },
      x2: {
        type: 'linear',
        display: false,
        max: 24
      },
      y: {
        stacked: false
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<canvas id="myChart"></canvas>

Related