3

Is there a way to create vertical lines (event lines, phase changes) using Chart.JS 2.0?

I've seen some examples online (see this related question), HOWEVER, when using Moment.js to create the horizontal axis, it is not possible to give LineAtIndex a moment.js date to create a line at that date.

    var originalLineDraw = Chart.controllers.line.prototype.draw;
Chart.helpers.extend(Chart.controllers.line.prototype, {
  draw: function() {
    originalLineDraw.apply(this, arguments);

    var chart = this.chart;
    var ctx = chart.chart.ctx;

    var index = chart.config.data.lineAtIndex;
    if (index) {
      var xaxis = chart.scales['x-axis-0'];
      var yaxis = chart.scales['y-axis-0'];

      ctx.save();
      ctx.beginPath();
      ctx.moveTo(xaxis.getPixelForValue(undefined, index), yaxis.top);
      ctx.strokeStyle = '#ff0000';
      ctx.lineTo(xaxis.getPixelForValue(undefined, index), yaxis.bottom);
      ctx.stroke();
      ctx.restore();
    }
  }
});

Here's a fiddle demonstrating the problem: https://jsfiddle.net/harblz/0am8vehg/

I believe my issue is that I don't properly understand this bit of code:

var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-0'];

If I am able to figure this out, I'll post a working fiddle here for any future users tackling the same project.

Thanks you for your time reading this :)

Community
  • 1
  • 1
Alex
  • 360
  • 4
  • 14

1 Answers1

2

I tried multiple plugins, but none could handle Charts with cartesian axes of type time. My rather simple solution:

First register the chart plugin globally:

Chart.plugins.register({
  drawLine: function (chart, xValue, color = 'rgba(87,86,86,0.2)') {
    const canvas = chart.chart
    const context = canvas.ctx

    context.beginPath()
    context.moveTo(xValue, 6) // top
    context.lineTo(xValue, canvas.height - 73) // bottom
    context.strokeStyle = color
    context.stroke()
  },

  afterDraw: function (chart) {
    const xScale = chart.scales['x-axis-0']

    if (chart.options.verticalLine) {
      chart.options.verticalLine.forEach((line) => {
        const xValue = xScale.getPixelForValue(line)

        if (xValue) {
          this.drawLine(chart, xValue)
        }
      })
    }
  }
})

Then add verticalLine Array to your chart definition:

options: {
   scales: { xAxes: [{ type: 'time' }] },
   verticalLine: ['2019-04-1', '2019-07-01', '2019-10-01'],
 }