You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3单折线图mousemove事件失效 悬浮圆点固定在折线末端不跟随鼠标

问题原因

你的问题出在二分查找的逻辑存在两处不匹配:

  • 类型不匹配:x.invert()返回的是Date对象,但bisector访问器返回的是原始字符串格式的日期,二者比较不会按时间逻辑计算,导致bisect结果固定
  • 数组顺序不匹配:你的原始数据是按日期倒序排列的,而d3.bisector默认针对升序数组做二分查找,顺序错误也会导致查找失效

修复方案

你可以按照以下步骤修改代码:

  1. 提前处理数据,将日期转为Date对象并按升序排序,替换lineChart函数内的原始data使用逻辑:
function lineChart({data}){
        const priceMargin = {top: 10, right: 30, bottom: 30, left: 60};
        const priceWidth = 1000 - priceMargin.left - priceMargin.right;  
        const priceHeight = 400 - priceMargin.top - priceMargin.bottom;
        
        const svg = d3.select(this)
            .append('svg')
                .attr("width", priceWidth + priceMargin.left + priceMargin.right)
                .attr("height", priceHeight + priceMargin.top + priceMargin.bottom)
            .append("g")
                .attr("transform", `translate(${priceMargin.left},${priceMargin.top})`);
        
        const parseDate = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z')
        // 新增:预处理数据 转日期+升序排序
        const processedData = data.map(item => ({
          ...item,
          date: parseDate(item.date)
        })).sort((a, b) => a.date - b.date)

        const x = d3.scaleTime()
            .domain(d3.extent(processedData, d => d.date))
            .range([0, priceWidth]);

        const y = d3.scaleLinear()
            .domain(d3.extent(processedData, d => d.close))
            .range([priceHeight, 0]);

        const line = d3.line()
            .x(d => x(d.date))
            .y(d => y(d.close))

        svg.append("path")
            .attr("fill", "none")
            .attr("stroke", "rgba(255, 31, 31)")
            .attr('d', line(processedData))
            .style("stroke-width", "2px")
        // 后续其他用到data的地方都替换为processedData
  1. 修改mousemove事件内的bisect查找和比较逻辑:
function mousemove() {
  const x0 = x.invert(d3.mouse(this)[0]),
  i = bisectDate(processedData, x0, 1),
  d0 = processedData[i - 1],
  d1 = processedData[i],
  // 转时间戳比较时间差
  d = x0.getTime() - d0.date.getTime() > d1.date.getTime() - x0.getTime() ? d1 : d0;
  focus.attr("transform", `translate(${x(d.date)},${y(d.close)})`);
  focus.select("text").text(formatCurrency(d.close));
}

修改完成后悬浮点就会跟随鼠标位置匹配对应的折线上的点了。

内容的提问来源于stack exchange,提问作者Taihuynh812

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:45:01