Chartjs-Drawing a mixed stacked horizontal bar/line in chartjs

1👍

It looks like this is the best solution:

https://codepen.io/kurkle/pen/ExxdyXQ

var ctx = document.getElementById("chart").getContext("2d");
var chart = new Chart(ctx, {
  type: "horizontalBar",
  data: {
    labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    datasets: [
      {
        label: "Bar1",
        data: [[2.5, 5.7]],
      },
      {
        label: "Bar2",
        data: [[6, 8]],
      },
      {
        label: "Bar3",
        data: [[9,10]],
      },
      {
        label: "Line",
        type: "line",
        backgroundColor: "rgb(75, 192, 192, 0.5)",
        borderColor: "rgb(75, 192, 192)",
        fill: false,
        tension: 0,
        data: [11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
        yAxisID: "line"
      }
    ]
  },
  options: {
    datasets: {
      horizontalBar: {
        backgroundColor: "rgb(255, 99, 132, 0.5)",
        borderColor: "rgb(255, 99, 132)",
        borderWidth: 1,
        barPercentage: 1,
        categoryPercentage: 1,
        yAxisID: "bar"
      }
    },
    scales: {
      yAxes: [
        {
          id: "bar",
          type: 'category',
          stacked: true,
          labels: ['bar'],
          offset: true
        },
        {
          id: "line",
          position: 'right',
          ticks: {
            min: 0,
            stepSize: 1
          }
        }
      ]
    }
  }
});

Credit to the original author of this code (Jukka Kurkela aka kurkle). He answered this on the chart.js GitHub issues page.

1👍

Hmh, that’s difficult… The only solution I would have is to create a bar chart with very many very small bars.

I made a JSBin with my solution but it’s far from perfect, but the only way to achieve it in chart.js. I didn’t test the performance as I don’t know your data, but this will be very important and the biggest problem.

Right now only one rectangle is possible, but it’s not difficult to improve it to multiple rectangles.

Here’s all my code, same as JSBin:

var chartData = {
  datasets: [{
    type: 'line',
    label: 'Dataset 1',
    borderColor: 'blue',
    borderWidth: 2,
    fill: false,
    data: []
  }, {
    type: 'bar',
    label: 'Dataset 2',
    backgroundColor: 'red',
    data: [],
  }]
};

var newData0 = []
var newData1 = []
var labels = []
var counter = 50

// Rectangle between two random Integers
var rectangleBetween = [Math.round(Math.random()*counter), Math.round(Math.random()*counter)]
rectangleBetween.sort(function(a, b){return a - b})

for (var i = 0; i < counter; i++) {
  labels.push(i)

  // Data for Dataset 1 (line):
  var newObj0 = {}
  newObj0.x = i
  // 50/50 chance of data
  if (Math.random()<0.5) {
    newObj0.y = Math.round(Math.random()*100)
  } else {
    newObj0.y = null
  }
  newData0.push(newObj0)

  // Data for Dataset 2 (bar):
  var newObj1 = {}
  if (i >= rectangleBetween[0] && i <= rectangleBetween[1]) {
    newObj1.x = i
    newObj1.y = 100
  } else {
    newObj1.x = i
    newObj1.y = 0
  }  
  newData1.push(newObj1)
}

chartData.datasets[0].data = newData0
chartData.datasets[1].data = newData1
chartData.labels = labels


var ctx = document.getElementById('chart').getContext('2d');
myMixedChart = new Chart(ctx, {
  type: 'bar',
  data: chartData,
  options: {
    responsive: true,
    spanGaps: true,
    title: {
      display: true,
      text: 'Chart.js Combo Bar Line Chart'
    },
    tooltips: {
      mode: 'index',
      intersect: true
    },
    scales: {
      xAxes: [{
        //barThickness: 80, // number (pixels) or 'flex'
        //maxBarThickness: 100, // number (pixels)
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        gridLines: {
          display: false
        }
      }]
    }
  }
});

Leave a comment