Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chartjs 2 - Stacked bar and unstacked line on same chart with same y axis

I've started using the latest beta of v2 of chart.js since I need to draw a chart that contains both a stacked bar chart and an unstacked line chart on the same chart. Here's an example of what I need:

enter image description here

In this chart the lines are not stacked and are all showing their natural values but the bar chart is stacked and shows the combined total of the values (including some negative values).

I've managed to get the two charts drawn together but so far I've only succeeded in either having both charts stacked or I've had to use two separate y-axis which ends up with 2 scales. There's an example of the separate y-axis in this fiddle:

yAxes: [{
    stacked: false,
    ticks: {
      beginAtZero: true
    }
  }, {
    id: "bar-y-axis",
    stacked: true,
    ticks: {
      beginAtZero: true
    },
    type: 'linear'
  }]

If I remove the first y-axis then I ended up with a single scale with the only problem being that the line chart is now stacked as well.

Is there any way to draw a chart like I need using chart.js?

like image 517
Roarster Avatar asked Jan 21 '16 16:01

Roarster


People also ask

What is better than a stacked bar chart?

An alternative to the bar or column panel charts is a dot plot. The advantage is that all points are plotted in the same XY space, allowing for easier comparisons.

How do you get a bar chart next to each other?

Click the Bar Groups tab. Expand the Bar Charts section. By default, each of the bar charts will be assigned to the same group (Group 1). Click next to one of the bar charts that you would like to be in a different group of stacked bars and select New Group.

What is CTX in chart JS?

js convention is to call it ctx . An object literal containing the data and the configuration options that Chart. js will use to build your chart. The required properties are type and data . In our example type is 'line' because we want a line chart.


1 Answers

You can get this functionality with a combination of setting a different yAxisID (e.g. yAxisID: "bar-stacked") to each of your datasets, and then adding a second options.scales.yAxes object. So you would have this as a dataset:

{
  label: 'Promoters',
  backgroundColor: "#aad700",
  yAxisID: "bar-stacked",
  data: [
    50, 44, 52, 62, 48, 58, 59, 50, 51, 52, 53, 54
  ]
}

and then you would add an additional yAxes (the first one will be the collection of your line datasets [no yAxisId in the example below], the second will be all of the bars you want stacked):

yAxes: [{
  stacked: false,
  ticks: {
    beginAtZero: true,
    min: 0,
    max: 100
  }
}, {
  id: "bar-stacked",
  stacked: true,
  display: false, //optional if both yAxes use the same scale
  ticks: {
    beginAtZero: true,
    min: 0,
    max: 100
  },
  type: 'linear'
}]

Full example is as follows:

<!doctype html>
<html>

<head>
  <title>Stacked Bar Chart</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.bundle.js"></script>
  <style>
    canvas {
      -moz-user-select: none;
      -webkit-user-select: none;
      -ms-user-select: none;
    }
  </style>
</head>

<body>
  <div style="width: 100%">
    <canvas id="canvas"></canvas>
  </div>
  <script>
    var barChartData = {
      labels: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
      datasets: [{
        data: [
          50, 30, 60, 70, 80, 90, 95, 70, 90, 20, 60, 95
        ],
        type: 'line',
        label: 'This Year',
        fill: false,
        backgroundColor: "#fff",
        borderColor: "#70cbf4",
        borderCapStyle: 'butt',
        borderDash: [],
        borderDashOffset: 0.0,
        borderJoinStyle: 'miter',
        lineTension: 0.3,
        pointBackgroundColor: "#fff",
        pointBorderColor: "#70cbf4",
        pointBorderWidth: 1,
        pointHoverRadius: 5,
        pointHoverBackgroundColor: "#70cbf4",
        pointHoverBorderColor: "#70cbf4",
        pointHoverBorderWidth: 2,
        pointRadius: 4,
        pointHitRadius: 10
      }, {
        data: [
          25, 40, 30, 70, 60, 50, 40, 70, 40, 80, 30, 90
        ],
        type: 'line',
        label: 'Last Year',
        fill: false,
        backgroundColor: "#fff",
        borderColor: "#737373",
        borderCapStyle: 'butt',
        borderDash: [10, 10],
        borderDashOffset: 0.0,
        borderJoinStyle: 'miter',
        lineTension: .3,
        pointBackgroundColor: "#fff",
        pointBorderColor: "#737373",
        pointBorderWidth: 1,
        pointHoverRadius: 5,
        pointHoverBackgroundColor: "#737373",
        pointHoverBorderColor: "#737373",
        pointHoverBorderWidth: 2,
        pointRadius: 4,
        pointHitRadius: 10
      }, {
        label: 'Promoters',
        backgroundColor: "#aad700",
        yAxisID: "bar-y-axis",
        data: [
          50, 44, 52, 62, 48, 58, 59, 50, 51, 52, 53, 54
        ]
      }, {
        label: 'Passives',
        backgroundColor: "#ffe100",
        yAxisID: "bar-y-axis",
        data: [
          20, 21, 24, 25, 26, 17, 28, 19, 20, 11, 22, 33
        ]
      }, {
        label: 'Detractors',
        backgroundColor: "#ef0000",
        yAxisID: "bar-y-axis",
        data: [
          30, 35, 24, 13, 26, 25, 13, 31, 29, 37, 25, 13
        ]
      }]
    };

    window.onload = function() {
      var ctx = document.getElementById("canvas").getContext("2d");
      window.myBar = new Chart(ctx, {
        type: 'bar',
        data: barChartData,
        options: {
          title: {
            display: true,
            text: "Chart.js Bar Chart - Stacked"
          },
          tooltips: {
            mode: 'label'
          },
          responsive: true,
          scales: {
            xAxes: [{
              stacked: true,
            }],
            yAxes: [{
              stacked: false,
              ticks: {
                beginAtZero: true,
                min: 0,
                max: 100
              }
            }, {
              id: "bar-y-axis",
              stacked: true,
              display: false, //optional
              ticks: {
                beginAtZero: true,
                min: 0,
                max: 100
              },
              type: 'linear'
            }]
          }
        }
      });
    };
  </script>
</body>

</html>
like image 124
Michael Oxborrow Avatar answered Sep 24 '22 07:09

Michael Oxborrow