Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-chartjs-2 vertical line when hovering over chart

I'm trying to create a linechart, using react-chartjs-2, that has a vertical line when hovering over the datapoints in the chart. Like in this picture below:

Chart requirements

I tried using the chartjs-plugin-annotation plugin, but with mixed results. I managed to create a static line, not understanding how or why it works. How should I achieve this? Am I onto something?

const data = {
    labels: [...week(d)],
    datasets: [
        {
            ...
            data: [10000, 9500, 7000, 4500, 2500, 1500, 500, 0],
        }
    ]
};

var line = [{
    type: "line",
    mode: "vertical",

    // ???
    scaleID: "y-axis-0",
    value: -20000,

    borderColor: "#2984c5",
    borderWidth: 1,
}];

const options = {
    tooltips: {
        xPadding: 20,
        yPadding: 10,
        displayColors: false,
        bodyFontSize: 16,
        bodyFontStyle: 'bold',
    },
    annotation: {
        annotations: line,
    },
    scales: {
        yAxes: [{
            gridLines: {
                drawBorder: false,
                tickMarkLength: 0,
            },
            ticks: {
                fontSize: 14,
                padding: 15,
                max: data.maxY,
                min: 0,
                maxTicksLimit: 6,
                fontColor: "#485465"
            }
        }],
        xAxes: [{
            ticks: {
                padding: 5,
                fontSize: 14,
                fontColor: "#485465",
            },
            gridLines: {
                display: false,
            },
        },

        ],
    },
    responsive: false,
}

I have my full code available here: https://codesandbox.io/s/y28mk3rn4z

like image 253
Grotle Avatar asked Sep 12 '25 00:09

Grotle


2 Answers

In case someone needs it for "react-chartjs-2": "^4.0.1".
This one worked for me based on previous answers:

import { Chart } from 'chart.js';
import { Line } from 'react-chartjs-2';

Chart.register(
  {
    id: 'uniqueid5', //typescript crashes without id
    afterDraw: function (chart: any, easing: any) {
      if (chart.tooltip._active && chart.tooltip._active.length) {
        const activePoint = chart.tooltip._active[0];
        const ctx = chart.ctx;
        const x = activePoint.element.x;
        const topY = chart.scales.y.top;
        const bottomY = chart.scales.y.bottom;
        ctx.save();
        ctx.beginPath();
        ctx.moveTo(x, topY);
        ctx.lineTo(x, bottomY);
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#e23fa9';
        ctx.stroke();
        ctx.restore();
      }
    }
  }
);
.
.
.
<Line 
    options={{
      ...options,
      interaction: {
        mode: 'index',
        intersect: false,
      }}} 
    data={data}
  />
like image 150
David Rios Avatar answered Sep 14 '25 13:09

David Rios


The below answer is correct it only needs some tweaks, Thanks Jordan.

Chart.pluginService.register({
    afterDraw: function(chart, easing) {
        if (chart.tooltip._active && chart.tooltip._active.length) {
            const activePoint = chart.controller.tooltip._active[0];
            const ctx = chart.ctx;
            const x = activePoint.tooltipPosition().x;
            const topY = chart.scales['y-axis-0'].top;
            const bottomY = chart.scales['y-axis-0'].bottom;
            ctx.save();
            ctx.beginPath();
            ctx.moveTo(x, topY);
            ctx.lineTo(x, bottomY);
            ctx.lineWidth = 2;
            ctx.strokeStyle = '#e23fa9';
            ctx.stroke();
            ctx.restore();
        }
    }
});

In the chart options we need to add the below config to display the line on near by hover.

tooltips: {
    mode: 'index',
    intersect: false
},
hover: {
    mode: 'index',
    intersect: false
}

PS: if there are multiple chart plotted together then above piece of code might cause problems. if we want to have this effect on a specific chart(e.g line) then we can add the below condition.

if (
    chart.tooltip._active &&
    chart.tooltip._active.length &&
    chart.config.type === 'line'
)

This worked for me, hope this help.

like image 24
arfath77 Avatar answered Sep 14 '25 12:09

arfath77