0

I am working on the latest version of Chart.js, i.e., v3.7.1. However, I notice that most of the configurations have been changed from those of version 2.x. My problem is that I would like to draw a vertical line everytime there is a mouseover the chart, but not necessary having the mouse on the data points, but can be above or below, as long as the mouse point is in line with a data point, a verical line is drawn. This is clearly illustrated by this code on JSFiddle. I tried this Solution on this platform but it fails to work since it is based on ChartJS v2.6.0. Anyone with an idea of doing this? Here are my codes:

LineChart.js

import React from "react";
import Chart from 'chart.js/auto';
import { Line } from "react-chartjs-2";
import 'chartjs-adapter-moment';

const newOptions = {
    responsive: true,
    plugins: {
        responsive: true,
        title: {
            display: true,
            text: 'Weekly Logs'
        },
    },
    scales: {
        x: {
            type: "time",
            time: {
                displayFormats: {
                    'day': 'dddd'
                }
            }
        }
    },
    interaction: {
        mode: "index",
        axis: 'y'
    }
};

const LineChart = ({ dataChart }) => {
  return <Line 
            data={dataChart} options={newOptions}
        />;
};

export default LineChart;
japheth
  • 373
  • 1
  • 10
  • 34

1 Answers1

1

You can use a custom plugin for this:

const plugin = {
  id: 'corsair',
  afterInit: (chart) => {
    chart.corsair = {
      x: 0,
      y: 0
    }
  },
  afterEvent: (chart, evt) => {
    const {
      chartArea: {
        top,
        bottom,
        left,
        right
      }
    } = chart;
    const {
      x,
      y
    } = evt.event;
    if (x < left || x > right || y < top || y > bottom) {
      chart.corsair = {
        x,
        y,
        draw: false
      }
      chart.draw();
      return;
    }

    chart.corsair = {
      x,
      y,
      draw: true
    }

    chart.draw();
  },
  afterDatasetsDraw: (chart, _, opts) => {
    const {
      ctx,
      chartArea: {
        top,
        bottom,
        left,
        right
      }
    } = chart;
    const {
      x,
      y,
      draw
    } = chart.corsair;

    if (!draw) {
      return;
    }

    ctx.lineWidth = opts.width || 0;
    ctx.setLineDash(opts.dash || []);
    ctx.strokeStyle = opts.color || 'black'

    ctx.save();
    ctx.beginPath();
    if (opts.vertical) {
      ctx.moveTo(x, bottom);
      ctx.lineTo(x, top);
    }
    if (opts.horizontal) {
      ctx.moveTo(left, y);
      ctx.lineTo(right, y);
    }
    ctx.stroke();
    ctx.restore();
  }
}

Chart.register(plugin)

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        borderColor: 'pink'
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderColor: 'orange'
      }
    ]
  },
  options: {
    plugins: {
      corsair: {
        horizontal: false,
        vertical: true,
        color: 'red',
        dash: [],
        width: 2
      }
    }
  },
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>

For you to use this in react, you only need the Chart.register line like so:

import React from "react";
import Chart from 'chart.js/auto';
import { Line } from "react-chartjs-2";
import 'chartjs-adapter-moment';

const plugin = {
  // Plugin code, see stack snipet above
}

Chart.register(plugin)
LeeLenalee
  • 27,463
  • 6
  • 45
  • 69
  • Hello, thanks for this response. However, I am just wondering, is this used as it is in React component? I am concerned about the last section of the snippet. – japheth Feb 23 '22 at 03:22
  • Thats only to make it show as a stack live sample, only thing that matters to you is the first part where I register the plugin. See updated answer – LeeLenalee Feb 23 '22 at 08:24
  • Thank you for your prompt response. I have tried that, however, I am getting this error on the console: `Uncaught TypeError: react_chartjs_2__WEBPACK_IMPORTED_MODULE_5__.Chart.register is not a function` – japheth Feb 23 '22 at 09:14
  • So, apparently, `Chart.register` is giving me an error. I am not sure if I should import something to solve this? – japheth Feb 23 '22 at 09:15
  • Hey, now after trying so many things, it is now working. I would like to inquire about one more thing: I want the intersection of the line graph and the vertical line to show data info as a pop-up. Right now, it does not pop up unless the mouse tip is on the data point. I am still trying on my end but if you could advise on that I will appreciate it so much. – japheth Feb 26 '22 at 09:45