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

如何在D3.js印度GeoJSON地图上正确显示邦名称并获取质心

解决D3.js印度地图质心NaN与邦名称显示问题

我来帮你排查并解决这两个核心问题:质心返回NaN、邦名称显示异常,问题根源在于投影配置错误和GeoJSON数据使用方式不符合D3的geo API要求。

1. 为什么质心返回NaN?

你调用path.centroid(d.d)时传入的d.d是路径字符串,而d3.geo.path.centroid()方法需要接收标准GeoJSON Feature或Geometry对象才能计算质心,传入字符串自然会返回NaN。同时,当前投影设置scale(1)和translate([0,0])完全没有适配地图边界,也会导致坐标计算完全失效。

2. 分步解决方案

步骤1:确保GeoJSON是标准格式

你的county.json必须是标准的FeatureCollection结构,示例如下:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "id": "AP",
        "n": "Andhra Pradesh"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [[/* 对应邦的经纬度坐标数组 */]]
      }
    }
    // 其他印度邦的Feature对象
  ]
}

步骤2:修正投影配置,自动适配容器

替换原有的投影代码,根据GeoJSON的边界自动计算合适的缩放和平移参数,让地图居中显示在容器内:

d3.json("county.json", function(json) {
  // 初始化投影和路径生成器
  var projection = d3.geo.mercator();
  var path = d3.geo.path().projection(projection);

  // 获取地图边界,计算适配容器的缩放和平移
  var bounds = path.bounds(json);
  var svgWidth = 600; // 对应你容器的高度600px
  var svgHeight = 600;
  // 计算缩放比例(预留5%的边距)
  var scale = 0.95 / Math.max(
    (bounds[1][0] - bounds[0][0]) / svgWidth,
    (bounds[1][1] - bounds[0][1]) / svgHeight
  );
  // 计算平移参数,让地图居中
  var translate = [
    (svgWidth - scale * (bounds[1][0] + bounds[0][0])) / 2,
    (svgHeight - scale * (bounds[1][1] + bounds[0][1])) / 2
  ];
  // 将参数应用到投影
  projection.scale(scale).translate(translate);

  // 后续绘制代码...
});

步骤3:修正路径与文本标签的绘制逻辑

适配标准GeoJSON结构,修正路径生成和质心计算的代码:

// 绘制邦的路径
svg.selectAll(".state")
  .data(json.features) // 取FeatureCollection里的features数组
  .enter()
  .append("path")
  .attr("class", "state")
  .attr("d", path) // 直接用path方法生成路径,无需手动取d.d
  .style("fill", function(d) {
    return sampleData[d.properties.id].color; // 从properties中取邦ID
  })
  .on("mousemove", mouseOver)
  .on("mouseout", mouseOut)
  .on("click", Click);

// 绘制邦名称标签
svg.selectAll("text")
  .data(json.features)
  .enter()
  .append("text")
  .attr("fill", "black")
  .attr("x", function(d) {
    return path.centroid(d)[0]; // 直接传入Feature对象计算质心
  })
  .attr("y", function(d) {
    return path.centroid(d)[1];
  })
  .attr("text-anchor", "middle")
  .attr("dy", ".35em")
  .text(function(d) {
    return d.properties.id; // 从properties中取邦ID
  });

步骤4:修正Tooltip的参数传递

现在数据是Feature对象,需要从properties属性中获取邦的名称和ID:

function mouseOver(d) {
  d3.select("#tooltip").transition().duration(200).style("opacity", .9);
  // 从d.properties中提取数据
  d3.select("#tooltip").html(tooltipHtml(d.properties.n, d.properties.id, sampleData[d.properties.id]))
    .style("left", (d3.event.layerX) + "px")
    .style("top", (d3.event.layerY) + "px");
}

3. 额外注意事项

  • 如果你的county.json确实是预先生成的路径字符串(非标准GeoJSON),则需要先将其转换为GeoJSON对象,或者改用d3.geom.centroid()计算路径的质心,但这种方式的可靠性远低于标准GeoJSON方案。
  • 确保sampleData中的键与GeoJSON里的properties.id完全匹配,避免出现找不到颜色的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:01:11