如何在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
相关产品推荐
相关产品推荐

