2

I'm trying to recreate this below chart with a stacked option on my background lines

enter image description here

But my attempts were unsuccessful with this image below as result

$(function() {
  var areaChartCanvas = $('#areaChart').get(0).getContext('2d')

  var areaChartData = {
    labels: ['', '', ''],
    datasets: [{
      backgroundColor: 'transparent',
      borderColor: 'black',
      pointRadius: false,
      data: [32, 12, 28],
      type: 'line'
    }, {
      backgroundColor: 'red',
      pointRadius: false,
      data: [20, 20, 20]
    }, {
      backgroundColor: 'orange',
      pointRadius: false,
      data: [40, 40, 40]
    }, {
      backgroundColor: 'cyan',
      pointRadius: false,
      data: [60, 60, 60]
    }]
  }

  var areaChartOptions = {
    maintainAspectRatio: false,
    responsive: true,
    legend: {
      display: false
    },
    scales: {
      xAxes: [{
        gridLines: {
          display: true,
        }
      }],
      yAxes: [{
        gridLines: {
          display: true,
        },
        stacked: true
      }]
    }
  }
  var areaChart = new Chart(areaChartCanvas, {
    type: 'line',
    data: areaChartData,
    options: areaChartOptions
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<canvas id="areaChart" style="height:250px"></canvas>

ideally, I want to be able to create 'AREAS' with different colors that will be stacked according to the interval I pass to it.

e.g:

cyan - 20

orange - 20

red - 20

but currently, I'm doing

cyan - 60

orange - 40

red - 20

Jonathan
  • 2,700
  • 4
  • 23
  • 41

1 Answers1

2

If I understand you correctly, I thought about different approach and extends the chart with Plugin[1] (Inspired by https://stackoverflow.com/a/49303362/863110)

Chart.pluginService.register({
  beforeDraw: function (chart, easing) {
    if (chart.config.options.fillColor) {
      var ctx = chart.chart.ctx;
      var chartArea = chart.chartArea;
      ctx.save();
      let delta = 0;
      const chartHeight = chartArea.bottom - chartArea.top;
      const bottomBarHeight = chart.height - chartHeight - chartArea.top;
      chart.config.options.fillColor.map(color => {
        const colorHeight = chartHeight * (color[0] / 100);
        const colorBottom = chartArea.bottom + colorHeight;
        ctx.fillStyle = color[1];

        const x = chartArea.left,
              y = chart.height - bottomBarHeight - colorHeight - delta,
              width = chartArea.right - chartArea.left,
              height = colorHeight;

        delta += height;
        ctx.fillRect(x, y, width, height);
        ctx.restore();
      })
    }
  }
});

var chartData = {
  labels: ['a', 'b', 'c', 'd'],
  datasets: [{
    label: 'value',
    borderColor: 'blue',
    data: [30, 50, 25, 10]
  }]
};

var ctx = document.getElementById("myChart").getContext("2d");
var myBar = new Chart(ctx, {
  type: 'line',
  data: chartData,
  options: {
    scales: {
      yAxes: [{ ticks: { max: 60 } }]
    },
    legend: { display: false },
    fillColor: [
      [20, 'red'],
      [20, 'blue'],
      [20, 'green'],
      [20, 'pink'],
      [20, 'yellow'],
    ]
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>

<canvas id="myChart" height="300" width="500"></canvas>

https://jsbin.com/lisuvuq/2/edit?js,output


[1] - With Plugin you can custom the chart's behaviour. When you use Plugin you get an API so you can "listen" to life cycle events of the chart (beforeDraw for example) and call your own code. The API calls your function and gives you data about the chart so you can use it in your code.
In this example, we're using the API to (1) Run a code before the chart been drawing (2) Using the data to calculate the areas of the different colors. (3) Draw additional shapes (ctx.fillRect) based on the calculation.

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135