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

如何在D3地图的鼠标悬停事件中显示多类数值?

搞定D3地图悬停同时显示价格与评分的问题

嘿,我瞅了你的代码,核心问题在于数据存储方式不对,还有tooltip的交互逻辑没写完整。现在你用valueHash存price和points时,同一个国家名的键会被后面的值覆盖,而且没给地图元素加鼠标悬停事件来展示多字段信息。我来一步步帮你修正:

1. 先把数据存对:每个国家对应一个包含price和points的对象

你原来的valueHash会让points覆盖price,改成对象结构就能同时存两个值了:

var valueHash = {};
data.forEach(function(d) {
  valueHash[d[MAP_KEY]] = {
    price: +d[MAP_VALUE],
    points: +d[MAP_VALUE2]
  };
});

2. 给国家路径加完整的鼠标悬停事件,用来展示tooltip

你原来的代码只到设置fill样式,没写鼠标事件,这部分是关键。给每个国家路径加上mouseover、mousemove、mouseout事件,就能控制tooltip显示内容和位置:

country.enter().insert("path")
  .attr("class", "country")
  .attr("d", path)
  .attr("id", function(d,i) { return d.id; })
  .style("fill", function(d) {
    // 这里我用price来设置颜色,你也可以换成points
    var countryData = valueHash[d.properties.name];
    if (countryData) {
      var colorIndex = quantize(countryData.price);
      var color = colors[colorIndex].getColors();
      return `rgb(${color.r}, ${color.g}, ${color.b})`;
    }
    return "#ccc"; // 没有数据的国家用灰色填充
  })
  .on("mouseover", function(d) {
    var countryData = valueHash[d.properties.name];
    if (!countryData) return; // 没有数据就不显示tooltip
    
    // 构建tooltip的HTML内容,同时展示两个字段
    var tooltipContent = `
      <div class="tooltip_key">${d.properties.name}</div>
      <div>平均价格: <span class="tooltip_value">${countryData.price}</span></div>
      <div>平均评分: <span class="tooltip_value">${countryData.points}</span></div>
    `;
    
    $("#tooltip-container").html(tooltipContent).show();
  })
  .on("mousemove", function() {
    // 让tooltip跟着鼠标移动,避免挡住地图
    $("#tooltip-container").css({
      top: d3.event.pageY + 15 + "px",
      left: d3.event.pageX + 15 + "px"
    });
  })
  .on("mouseout", function() {
    $("#tooltip-container").hide();
  });

3. 修正颜色比例尺(可选,看你想用哪个字段做颜色区分)

如果你想用price来区分颜色,比例尺的domain要基于price的范围,原来的写法有问题,改成这样:

var quantize = d3.scale.quantize()
  .domain([
    d3.min(data, function(d){ return +d[MAP_VALUE]; }), // MAP_VALUE是price
    d3.max(data, function(d){ return +d[MAP_VALUE]; })
  ])
  .range(d3.range(COLOR_COUNTS).map(function(i) { return i; }));

要是想用points做颜色区分,把上面的MAP_VALUE换成MAP_VALUE2就行。

小提醒

你的CSV里的国家名称必须和地图里的d.properties.name完全匹配,不然会找不到对应数据哦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:33:15