如何在D3绘制的SVG世界地图上显示国家名称?
在D3世界地图上显示各国名称的实现方法
嘿,要给你的D3世界地图加上各国名称其实不难,核心就是找对每个国家的中心位置,再把名称和地图数据对应上就行。结合你的现有代码,我给你梳理具体实现步骤:
步骤1:先搞定国家名称与ID的映射
你用的这个world-110m2.json只存了国家的地理形状和ID,没直接带名称字段,所以得先整个映射表,把每个国家的ID对应到它的名称上。我给你写个示例,你可以按需补全:
// 国家ID→名称的映射(示例部分数据,需要你补充完整哦) const countryNames = { "4": "Afghanistan", "8": "Albania", "12": "Algeria", "20": "Andorra", "24": "Angola", // 剩下的国家可以查topojson对应的ID来补充 };
步骤2:添加国家名称的文本标签
在你画完国家路径的代码后面,加一段生成文本的逻辑就行。这里用D3的path.centroid()来获取每个国家的中心位置,把文本放在那儿:
// 给每个国家加名称文本 g.selectAll("text.country-name") .data(topojson.object(topology, topology.objects.countries).geometries) .enter() .append("text") .attr("class", "country-name") // 用质心坐标定位文本 .attr("x", d => path.centroid(d)[0]) .attr("y", d => path.centroid(d)[1]) // 让文本在中心位置居中对齐 .attr("text-anchor", "middle") .attr("font-size", "10px") .attr("fill", "#333") // 根据ID匹配对应的国家名称,找不到就显示空 .text(d => countryNames[d.id] || "");
步骤3:优化显示效果(可选)
如果遇到小国家名称重叠、看不清的情况,可以做点优化:
- 过滤掉面积太小的国家,比如岛国,避免挤在一起:
.text(d => { // 计算国家面积,小于阈值就不显示名称 const area = d3.geoArea(d); return area > 0.001 ? countryNames[d.id] || "" : ""; })
- 给文本加个白色阴影,在深色地图上更清楚:
.country-name { text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff; }
整合后的完整代码片段
把这些代码加到你的现有逻辑里,核心部分大概是这样:
d3.json("https://gist.githubusercontent.com/d3noob/5193723/raw/world-110m2.json", function (error, topology) { // 先定义国家名称映射 const countryNames = { "4": "Afghanistan", "8": "Albania", "12": "Algeria", // 记得补全其他国家哦 }; let world = g .selectAll("path") .data(topojson.object(topology, topology.objects.countries).geometries) .enter() .append("path") .attr("d", path); // 添加国家名称文本 g.selectAll("text.country-name") .data(topojson.object(topology, topology.objects.countries).geometries) .enter() .append("text") .attr("class", "country-name") .attr("x", d => path.centroid(d)[0]) .attr("y", d => path.centroid(d)[1]) .attr("text-anchor", "middle") .attr("font-size", "10px") .attr("fill", "#333") .text(d => countryNames[d.id] || ""); // 城市标记的代码保持不变 let locations = g .selectAll("circle") .data(cities) .enter() .append("circle"); });
内容的提问来源于stack exchange,提问作者Suresh.W
相关产品推荐
相关产品推荐

