Search code examples
javascriptchartschart.jslinechart.js2

How to correctly create a straight line in chart.js with mixed type?


Help me find my mistake.

I use chart.js 2.7.0. I have a bar chart and want to add two lines. One of them should be straight via all chart. I tried two ways, but it didn't help me.

In the first way, I added to datasets values:

export const chartConfiguration = () => ({
  type: 'bar',
  data: {
    labels: null,
    datasets: [
      {
        label: 'Hourly',
        fill: false,
        data: [0.3494, 0.3361, 0.325, 0.3224],
        borderColor: '#ff0000',
        pointBackgroundColor: '#ff0000',
        type: 'line',
      },
      {
        label: 'Average',
        fill: false,
        data: Array(4).fill(1),
        borderColor: '#d67735',
        pointBackgroundColor: '#d67735',
        type: 'line',
        pointRadius: 0,
        pointHitRadius: 0,
        lineTension: 0,
        beginAtZero: true
      }]
  },
  options: {
    title: {
      display: true,
      position: 'top',
      fontColor: '#3f7ba2',
      fontStyle: 550,
      fontSize: 15
    },
    legend: {display: false},
    scales: {
      xAxes: [{
        stacked: true,
        ticks: {
          stepSize: 1,
          min: 0,
          autoSkip: false,
          fontColor: '#3f7ba2',
          fontStyle: 550,
          fontSize: 11,
          padding: 5
        },
        gridLines: {
          color: '#dedfe7'
        }
      }],
      yAxes: [{
        stacked: true,
        ticks: {
          min: 0,
          fontColor: '#62aae8',
          padding: 5
        },
        gridLines: {
          color: '#dedfe7',
          tickMarkLength: 15
        }
      }],
    },
    annotation: {
      events: ['mouseenter', 'mouseleave'],
      annotations: []
    },});

I thought that worked, but I was mistaken. The problem is the first line with the label 'Hourly' has a value = 0.3494, and the second line with the label: 'Average' has a value = 1. Chart.js draw second line not by value 1, it draws it by value 0.3494 + 1 = 1.3494. I tried to find any options like beginFromZero, but here it isn't present Here is screenshot: enter image description here

  1. I tried the second way: I added a plugin, but it doesn't work at all, and I don't know why:
export const chartConfiguration = () => ({
  type: 'bar',
  data: {
    labels: null,
    datasets: [{
      label: ' ',
      data: [1.9 , 2.0, 1.7, 1.8],
      borderColor: '#b1c8de',
      backgroundColor: '#b1c8de',
      pointBackgroundColor: '#b1c8de',
      tension: 0,
      fill: false,
      offsetGridLines: true
    }]
  },
  options: {
    title: {
      display: true,
      position: 'top',
      text: currentFullDate,
      fontColor: '#3f7ba2',
      fontStyle: 550,
      fontSize: 15
    },
    legend: {display: false},
    scales: {
      xAxes: [{
        stacked: true,
        ticks: {
          stepSize: 1,
          min: 0,
          autoSkip: false,
          fontColor: '#3f7ba2',
          fontStyle: 550,
          fontSize: 11,
          padding: 5
        },
        gridLines: {
          color: '#dedfe7'
        }
      }],
      yAxes: [{
        stacked: true,
        ticks: {
          min: 0,
          fontColor: '#62aae8',
          padding: 5
        },
        gridLines: {
          color: '#dedfe7',
          tickMarkLength: 15
        }
      }],
    },
    config : {
        plugins: {
            afterDatasetsDraw: function(chart) {
              let lineAt = 1;
              const ctxPlugin = chart.chart.ctx;
              const xAxe = this._chart.scales[chart.config.options.scales.xAxes[0].id];
              const yAxe = this._chart.scales[chart.config.options.scales.yAxes[0].id];
              if (yAxe.min !== 0) {
                return;
              }
              ctxPlugin.strokeStyle = '#d67735';
              ctxPlugin.beginPath();
              lineAt = (lineAt - yAxe.min) * (100 / yAxe.max);
              lineAt = (100 - lineAt) / 100 * (yAxe.height) + yAxe.top;
              ctxPlugin.moveTo(xAxe.left, lineAt);
              ctxPlugin.lineTo(xAxe.right, lineAt);
              ctxPlugin.stroke();
            }
        } }
});

Solution

  • Like I said in my comment this behaviour happens because you stack your y axes. You need to set stacked: false in your y axes object