Chart.js 悬停线在鼠标离开时不会消失

问题描述 投票:0回答:1

我有一个使用 react-chartjs-2 库创建的图表。我创建了一个自定义插件来绘制垂直和水平悬停线。将鼠标悬停在图表上时,悬停线会正确显示,但是当我将鼠标移离图表区域时,悬停线不会消失。

相关代码如下:

import React from 'react';
import { Line } from 'react-chartjs-2';
import { Chart, registerables } from 'chart.js';
import dayjs from 'dayjs';

Chart.register(...registerables);

  const hoverLinePlugin = {
    id: 'hoverLine',
    tooltip: null,
    beforeInit: (chart) => {
      const canvas = chart.canvas;
      hoverLinePlugin.tooltip = document.createElement('div');
      hoverLinePlugin.tooltip.id = 'CanvasPriceGraph@#!'
      const tooltip = hoverLinePlugin.tooltip;
      tooltip.style.position = 'absolute';
      tooltip.style.background = '#1f232e';
      tooltip.style.padding = '1px 12px';
      tooltip.style.borderRadius = '4px';
      tooltip.style.display = 'none';
      tooltip.style.boxShadow = '-3px 3px 5px rgba(0, 0, 0, 0.2)';
      tooltip.style.zIndex = 25;

      document.body.appendChild(tooltip);
  
      canvas.addEventListener('mousemove', (event) => {
        
        const { left } = canvas.getBoundingClientRect();
        const mouseX = event.clientX - left;
  
        // Get the x-coordinate of datapoint 0
        const datapointX0 = chart.scales.x.getPixelForValue(0);
  
        // Only update the chart's mouseX if mouseX is greater than or equal to datapointX0
        if (mouseX >= datapointX0 && mouseX <= chart.chartArea.right) {
          chart.mouseX = mouseX;
          chart.update();
  
          // Update tooltip position and content
          const datasetIndex = 0; // Adjust this based on your dataset
          const dataIndex = chart.scales.x.getValueForPixel(mouseX);
          const dataset = chart.data.datasets[datasetIndex];
          if (dataset && dataset.data[dataIndex] !== undefined) {
            tooltip.style.display = 'none';
            tooltip.style.left = '';
            const yValue = dataset.data[dataIndex].toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
            const xLabel = chart.data.labels[dataIndex];
            
            // Check if the tooltip would extend beyond the right edge of the chart
            const chartRight = canvas.getBoundingClientRect().right;
            if (mouseX > chartRight / 2) {
              tooltip.style.left = '';
              tooltip.style.right = window.innerWidth - event.x + 20 + 'px';
            } else {
              tooltip.style.right = '';
              tooltip.style.left = event.x + 20 + 'px';
            }
            
            tooltip.style.top = event.pageY + 'px';

            tooltip.innerHTML = `
            <div style='position: relative;'>
              <div style='font-size: 16px; font-weight: 100; color: #ffffff;'>$${yValue}</div>
              <div style='font-size: 10px; color: #E2E8F0;'>${dayjs(xLabel).format('DD MMM YY')}</div>
              ${hashSet.has(memory[1]) ? 
              "<div style='font-size: 10px; color: #E2E8F0;'>" + dayjs(xLabel).format('HH:mm') + "</div>" :
              ''
              }
            </div>`;
            tooltip.style.display = 'block';
          } else {
            tooltip.style.display = 'none';
          }
        }
      });
      // Hide the tooltip when leaving the canvas
      canvas.addEventListener('mouseleave', () => {
        hoverLinePlugin.tooltip.style.display = 'none';
      });

      // Hide the tooltip when window is resized
      window.addEventListener('resize', () => {
        hoverLinePlugin.tooltip.style.display = 'none';
      });
    },

    beforeDraw: (chart) => {
      const { ctx, chartArea: { bottom, top, left, right }, mouseX } = chart;
      if (mouseX !== undefined) {
        ctx.save();
        ctx.beginPath();
        ctx.lineWidth = 1;
        ctx.strokeStyle = '#D1D4DC';
  
        // Get the x-coordinate of datapoint 0
        const datapointX0 = chart.scales.x.getPixelForValue(0);
  
        // Use Math.max to ensure the hoverline doesn't go to the left of datapoint 0
        const hoverlineX = Math.max(mouseX, datapointX0);
  
        // Find the corresponding dataset index and data point index
        const dataIndex = chart.scales.x.getValueForPixel(hoverlineX);    
  
        // Retrieve the y-coordinate value for the given x-coordinate
        const pointElement = chartRef.current.getDatasetMeta(0).data[dataIndex];
        const hoveredDataX = pointElement?.x;
        const hoveredDataY = pointElement?.y;
  
        ctx.moveTo(hoveredDataX, bottom);
        ctx.lineTo(hoveredDataX, top);
        ctx.stroke();
        ctx.closePath();

        ctx.beginPath();
        ctx.moveTo(left, hoveredDataY);
        ctx.lineTo(right, hoveredDataY);
        ctx.stroke();
        ctx.closePath();

        ctx.beginPath();
        ctx.strokeStyle = memory[0];
        ctx.arc(hoveredDataX, pointElement?.y, 3, 0 * Math.PI, 2 * Math.PI);
        ctx.fillStyle = memory[0];
        ctx.fill();
        ctx.closePath();
      }
    },

    beforeDestroy: () => {
      hoverLinePlugin.tooltip.style.display = 'none';
    },
    
  };

return chartData.labels ? <Line id='canvas' ref={chartRef} data={data} options={options} plugins={[hoverLinePlugin]}/> : null;

如何修改此代码以删除鼠标离开时的悬停线?

如有任何帮助,我们将不胜感激。谢谢!

javascript reactjs charts chart.js
1个回答
0
投票

鼠标移出时,我们将删除工具提示,我们只需要在隐藏工具提示时停止执行

beforeDraw
,这一行更改似乎可以完成工作。

...
beforeDraw: (chart) => {
    if(hoverLinePlugin.tooltip.style.display === 'none') {
      return;
    }
    ...

堆栈闪电战

© www.soinside.com 2019 - 2024. All rights reserved.