3
votes

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

2
using chrome 72, I don't get the vertical lines when you hover over a point.. - jsdeveloper
@jsdeveloper yes, that's what I need help with - Grotle
ah ok understood - jsdeveloper

2 Answers

1
votes

Just looked into this exact thing and this will get you there! It won't do the fills on either side of the line, but it creates the vertical line!

componentWillMount() {
    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-1'].top;
          const bottomY = chart.scales['y-axis-1'].bottom;
          ctx.save();
          ctx.beginPath();
          ctx.moveTo(x, topY);
          ctx.lineTo(x, bottomY);
          ctx.lineWidth = 2;
          ctx.strokeStyle = '#e23fa9';
          ctx.stroke();
          ctx.restore();
        }
      }
    });
  }

Also for anyone with multiple datasets you can add this into your options for tooltips on all lines at once.

tooltips: {
          mode: 'x'
        },
1
votes

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 peace 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.