如何使用D3.js将GEOJSON格式的越南地图居中显示?
解决D3.js加载国家地图无法居中的问题
问题根源
你当前加载的GeoJSON是全球所有国家的边界数据集,而非仅包含越南的边界数据。调用projection.fitSize([width, height], bb)时,D3会将整个世界地图缩放到SVG容器内,导致越南区域被压缩得极小,看起来像是显示了全球范围。
解决方案
从加载的全球数据中筛选出目标国家的Feature,再基于单个国家的GeoJSON数据配置投影:
- 筛选目标国家Feature:通过GeoJSON的属性字段(比如
properties.name或properties.iso_a3)定位到目标国家的边界数据 - 基于单个国家数据配置投影:用筛选后的Feature计算投影中心、适配容器尺寸
修改后的完整代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vietnam</title> <style> html, body { margin: auto; width: 100%; padding: 0; height: 100%; overflow: hidden; font-size: 12px; font-weight: bold; font-family: arial; position: absolute; display: flex; align-items: center; text-align: center } path { stroke: orange; stroke-width: 0.15vw; fill: black; } svg { display: block; margin: 0 auto; font-size: 2vw; font-family: arial; font-weight: bolder; border: 0px solid white; } </style> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="http://d3js.org/topojson.v0.min.js"></script> <script src='https://unpkg.com/@turf/turf@6/turf.min.js'></script> </head> <body> <script type="text/javascript"> d3.json("https://gist.githubusercontent.com/teglouis27/3c2fe0d34a64c91d04695f24530aa423/raw/7e7a91530b34234043995cd923a1cbc61f4fd4c6/vietnamCountryBorders").then(function(bb) { let width = 700, height = 700; // 从全球数据中筛选出越南的边界Feature const vietnamFeature = bb.features.find(feature => feature.properties.name === "Vietnam"); if (!vietnamFeature) { console.error("未找到越南的边界数据"); return; } // 基于越南的Feature配置投影 let projection = d3.geoEqualEarth() .fitSize([width, height], vietnamFeature); let geoGenerator = d3.geoPath().projection(projection); let svg = d3.select("body").append('svg') .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", `0 0 ${width} ${height}`) .style("width", width) .style("height", height); // 绘制越南边界 svg.append('g') .selectAll('path') .data([vietnamFeature]) // 使用筛选后的单个Feature .join('path') .attr('d', geoGenerator) .attr('fill', '#088') .attr('stroke', '#000'); }); </script> </body> </html>
多国家通用扩展
如果要支持多个国家,只需将筛选逻辑封装成函数,传入目标国家名称即可:
function getCountryFeature(globalData, countryName) { return globalData.features.find(feature => feature.properties.name === countryName); } // 示例:加载泰国地图 const thailandFeature = getCountryFeature(bb, "Thailand");
内容的提问来源于stack exchange,提问作者Romogi
相关产品推荐
相关产品推荐

