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

D3.js嵌套数据折线图鼠标悬停功能实现求助

问题根源

你的<path>元素绑定的是groupclusters中的分组对象(结构为{key: ..., values: [数据点数组]}),而非单个数据点,所以直接访问d.mtbname必然取不到值,导致tooltip显示undefined。

解决方案

下面提供两种可行的实现方式:

方案一:给数据点添加可交互圆点(简单直观)

在绘制折线后,为每个分组的单个数据点添加小圆点,直接绑定单条数据实现悬停:

// 初始化tooltip(如果还没做的话)
var tooltip1 = d3.select("body").append("div")
  .style("position", "absolute")
  .style("opacity", 0)
  .style("background", "#fff")
  .style("border", "1px solid #ccc")
  .style("padding", "8px")
  .style("border-radius", "4px");

// 绘制折线(保留你原有代码)
svg.append("path")
  .attr("fill", "none")
  .attr("stroke", '#a65628')
  .attr("stroke-width", 1)
  .attr("class", "line")
  .attr("d", function(d){
    return d3.line()
      .x(function(d) { return x(d.mtbname); })
      .y(function(d) { return y(+d.clustcenters); })(d.values);
  });

// 为每个数据点添加可悬停圆点
svg.selectAll(".dot")
  .data(function(d) { return d.values; }) // 绑定单个数据点
  .enter()
  .append("circle")
  .attr("class", "dot")
  .attr("cx", function(d) { return x(d.mtbname); })
  .attr("cy", function(d) { return y(+d.clustcenters); })
  .attr("r", 3)
  .style("fill", "#a65628")
  .on('mouseover', function(d){
    tooltip1.transition().duration(10)
      .style("opacity", 0.8)
      .style("left", `${d3.event.pageX + 20}px`)
      .style("top", `${d3.event.pageY - 35}px`);
    tooltip1.html(`<p>名称:${d.mtbname}</p><p>数值:${d.clustcenters}</p>`);
  })
  .on('mouseout', function(){
    tooltip1.transition().duration(100).style("opacity", 0);
  });

可以给圆点加CSS过渡效果优化体验:

.dot {
  transition: r 0.2s;
}
.dot:hover {
  r: 5;
}

方案二:直接在折线上实现悬停(无圆点)

通过D3的bisector工具,根据鼠标位置计算对应的数据点:

// 初始化tooltip(如果还没做的话)
var tooltip1 = d3.select("body").append("div")
  .style("position", "absolute")
  .style("opacity", 0)
  .style("background", "#fff")
  .style("border", "1px solid #ccc")
  .style("padding", "8px")
  .style("border-radius", "4px");

// 定义bisector,用于匹配x轴数据
var bisectIndex = d3.bisector(function(d) { return mtbsnameslist.indexOf(d.mtbname); }).left;

// 绘制折线并绑定悬停事件
svg.append("path")
  .attr("fill", "none")
  .attr("stroke", '#a65628')
  .attr("stroke-width", 1)
  .attr("class", "line")
  .attr("d", function(d){
    return d3.line()
      .x(function(d) { return x(d.mtbname); })
      .y(function(d) { return y(+d.clustcenters); })(d.values);
  })
  .on('mouseover', function(d) {
    // 获取鼠标在SVG内的x坐标
    var mouseX = d3.mouse(this)[0];
    // 转换为对应的x轴索引
    var targetIndex = bisectIndex(mtbsnameslist, x.invert(mouseX));
    // 找到对应的数据点
    var targetPoint = d.values.find(item => item.mtbname === mtbsnameslist[targetIndex]);

    if (targetPoint) {
      tooltip1.transition().duration(10)
        .style("opacity", 0.8)
        .style("left", `${d3.event.pageX + 20}px`)
        .style("top", `${d3.event.pageY - 35}px`);
      tooltip1.html(`<p>名称:${targetPoint.mtbname}</p><p>数值:${targetPoint.clustcenters}</p>`);
    }
  })
  .on('mouseout', function(){
    tooltip1.transition().duration(100).style("opacity", 0);
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 00:42:50