Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dashed line for missing data in Chart.JS (spanGaps style)

Tags:

chart.js

I have a chart with data points that are null. Chart.js does the correct thing and skips those data points but I would like to have a 'dashed' line fill in the missing parts. For example, in the below code the line should be solid as in the CodePen link, but should be dashed from "Blue" to "Yellow". I know the spanGaps option is available but I would like to apply a different style to it.

Does anyone have any thoughts on how to accomplish this? I am using Chart.js 2.x

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
    type: 'line',
    data: {
        labels: ["Red", "Blue", "Orange", "Yellow"],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, null, 3]
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});

CodePen

like image 453
bep Avatar asked Nov 09 '22 03:11

bep


1 Answers

The Plugin Core API offers a range of hooks that may be used for performing custom code. You can use the beforeDraw hook to draw lines of different style between different datapoints using text directly on the canvas using CanvasRenderingContext2D.

Please take a look at the runnable code snippet below:

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
  type: 'line',
  plugins: [{
    beforeDraw: chart => {
      var ctx = chart.chart.ctx;
      ctx.save();
      let xAxis = chart.scales['x-axis-0'];
      let yAxis = chart.scales['y-axis-0'];
      let dataset = chart.data.datasets[0];
      var valueFrom = null;
      var valueFromIndex = 0;
      var xFrom = null;
      let yFrom = null;
      ctx.strokeStyle = dataset.borderColor;
      dataset.data.forEach((value, index) => {
        if (value != null) {
          var x = xAxis.getPixelForTick(index);
          var y = yAxis.getPixelForValue(value);
          if (valueFrom != null) {
            ctx.lineWidth = dataset.borderWidth;
            if (index - valueFromIndex > 1) {
              ctx.setLineDash([5, 5]);
            } else {
              ctx.setLineDash([]);
            }
            ctx.beginPath();
            ctx.moveTo(xFrom, yFrom);
            ctx.lineTo(x, y);
            ctx.stroke();
          }
          valueFrom = value;
          valueFromIndex = index;
          xFrom = x;
          yFrom = y;
        }
      });
      ctx.restore();
    }
  }],
  data: {
    labels: ["A", "B", "C", "D", "E", "F", "G"],
    datasets: [{
      label: 'My Dataset',
      data: [12, 19, null, 3, 6, null, 8],
      backgroundColor: 'rgba(255, 99, 132, 0.6)',
      borderColor: 'rgb(255, 99, 132)',
      borderWidth: 3,
      showLine: false,
    }]
  },
  options: {
    animation: {
      duration: 0
    },
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="90"></canvas>
like image 122
uminder Avatar answered Jan 04 '23 01:01

uminder