我有一个使用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;

如何修改此代码以删除鼠标左键上的悬停线?

任何帮助都将不胜感激.谢谢!

推荐答案

在鼠标输出时,我们删除了工具提示,当工具提示隐藏时,我们只需要停止执行beforeDraw,这一行更改似乎完成了工作.

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

stackblitz

Javascript相关问答推荐

使用redux-toolet DelivercThunks刷新访问令牌

JS生成具有给定数字和幻灯片计数的数组子集

网页自检测外部元素无法加载

为什么当我解析一个promise时,输出处于挂起状态?

如何调用名称在字符串中的实例方法?

如何从隐藏/显示中删除其中一个点击?

获取Uint8ClampedArray中像素数组的宽度/高度

如何将Cookie从服务器发送到用户浏览器

制作钢琴模拟器,并且在控制台中不会执行或显示该脚本

单个HTML中的多个HTML文件

在forEach循环中获取目标而不是父对象的属性

如何在Angular拖放组件中同步数组?

将对象推送到数组会导致复制

如何在Jest中模拟函数

如何使用Cypress在IFRAME中打字

Chrome上的印度时区名S有问题吗?

如何在Firebase中读取对象的特定字段?

KeyboardEvent:检测到键具有打印的表示形式

使用Java脚本筛选数组中最接近值最小的所有项

JS/css:将数字输入的S函数和可调整大小的元素S函数绑定在一起