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

在D3 Hexbin中实现鼠标悬停时目标及周边六边形半径增大效果

实现Hexbin悬停时中心+邻域六边形放大效果

嘿,作为D3新手能搞定基础悬停已经超棒啦!要实现这个“中心+邻域弹出”的效果,咱们可以分几步来落地:

1. 先建立六边形的邻居查询映射

D3生成的hexbin不会自动记录每个六边形的相邻元素,所以咱们需要先把所有六边形存到一个Map里,用x,y坐标作为键,这样能快速查找任意六边形的邻居:

// 假设你已经生成了hexbins数组(来自hexbin(data))
const binMap = new Map();
hexbins.forEach(bin => {
  // 用x和y的拼接字符串作为唯一键
  binMap.set(`${bin.x},${bin.y}`, bin);
});

2. 绑定悬停事件,处理放大逻辑

接下来给每个六边形绑定mouseover和mouseout事件,在悬停时找到当前六边形的6个邻居(如果存在),然后一起放大;移出时恢复原状:

const baseRadius = 10; // 你的基础六边形半径
const hoverRadius = baseRadius * 1.2; // 放大后的半径,可自定义

svg.selectAll(".hexagon")
  .data(hexbins)
  .enter()
  .append("path")
  .attr("class", "hexagon")
  .attr("d", d => d3.hexbin().hexagon(baseRadius))
  .attr("transform", d => `translate(${d.x},${d.y})`)
  // 鼠标悬停事件
  .on("mouseover", (event, currentBin) => {
    // 生成当前六边形的6个可能邻居的坐标键
    // 注意:Hexbin的偶数行和奇数行水平偏移不同,所以邻居坐标要区分处理
    const neighborKeys = [
      `${currentBin.x + 1},${currentBin.y}`,
      `${currentBin.x - 1},${currentBin.y}`,
      `${currentBin.x},${currentBin.y + 1}`,
      `${currentBin.x},${currentBin.y - 1}`,
      // 偶数行的下邻居是x+1,奇数行是x-1
      `${currentBin.x + (currentBin.y % 2 === 0 ? 1 : -1)},${currentBin.y + 1}`,
      // 偶数行的上邻居是x-1,奇数行是x+1
      `${currentBin.x + (currentBin.y % 2 === 0 ? -1 : 1)},${currentBin.y - 1}`
    ];

    // 收集当前六边形+存在的邻居
    const activeBins = [currentBin];
    neighborKeys.forEach(key => {
      const neighborBin = binMap.get(key);
      if (neighborBin) activeBins.push(neighborBin);
    });

    // 给目标六边形添加过渡动画,放大半径
    svg.selectAll(".hexagon")
      .filter(bin => activeBins.includes(bin))
      .transition()
      .duration(200) // 动画时长,可调整
      .attr("d", d3.hexbin().hexagon(hoverRadius));
  })
  // 鼠标移出事件
  .on("mouseout", () => {
    // 恢复所有六边形的基础半径
    svg.selectAll(".hexagon")
      .transition()
      .duration(200)
      .attr("d", d3.hexbin().hexagon(baseRadius));
  });

3. 关键注意点

  • 邻居坐标的准确性:Hexbin的布局中,偶数行和奇数行的水平偏移是相反的,所以上面的代码用currentBin.y % 2来区分,你可以打印几个六边形的x/y值来验证是否正确匹配邻居。
  • 边缘六边形处理:代码里已经判断了邻居是否存在,所以悬停边缘六边形时,只会放大存在的邻居,不会报错。
  • 动画优化:用transition做平滑过渡比直接修改属性更自然,你可以调整duration的值来控制动画快慢。
  • 样式自定义:如果需要给放大的六边形加颜色高亮,可以在mouseover时给它们添加额外的CSS类,比如.active-hex { fill: #ff7f0e; },然后在filter后加上.classed("active-hex", true),移出时再移除这个类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:33:11