向 d3-geomap 添加标签的正确方法

Right way to add labels to d3-geomap

我尝试向使用 d3-geomap 完成的地图添加标签,但无法正常工作。

分区统计图本身绘制正确,但添加标签效果不佳。标签显示在错误的位置。

绘制地图后,我再次加载了 topojson 文件,然后像这样添加文本块:

d3.json("https://d3-geomap.github.io/d3-geomap/topojson/countries/ESP.json").then(function(es) {

      let path = d3.geoPath().projection(d3.geoMercator());
      svg.select("svg").append("g")
          .selectAll("labels")
          .data(topojson.feature(es, es.objects.units).features)
          .enter().append("text")
          .attr("class", "place-label")
          .attr("x", function(d) { return path.centroid(d)[0]; })
          .attr("y", function(d) { return path.centroid(d)[1]; })
          .attr("text-anchor","middle")
          .text(function(d) { return d.properties.name; });
    });

这里的问题是我无法确定标签的正确位置。我还尝试对多边形应用相同的变换,但随后具有相同的 y 位置。

这是 bl.ocks 上的示例。

我对您的代码进行了一些更改并发布了它 in this gist。在本地测试时,地图显示如下图。在此尺寸下,标签效果不佳,但如果您调整地图大小 and/or 显示较少的标签应该没问题。

有关更改的一些信息。每当你想用 d3-geomap 在地图上绘制一些东西时,它应该放在 postUpdate 函数中。通过这种方式,地图已经呈现,并且可以通过您创建的地图对象访问其 SVG 元素、地理数据和路径对象。无需再次加载 Topojson 文件。传递给 postUpdate 的函数如下所示:

function drawLabels() {
    map.svg.append("g").attr('class', 'zoom')
        .selectAll("text")
        .data(topojson.feature(map.geo, map.geo.objects.units).features)
        .enter().append("text")
        .attr("class", "place-label")
        .attr("x", function(d) { return map.path.centroid(d)[0]; })
        .attr("y", function(d) { return map.path.centroid(d)[1]; })
        .attr("text-anchor","middle")
        .text(function(d) { return d.properties.name; })
        .on('click', map.clicked.bind(map));
}

This page of the documentation 显示可用的地图属性和访问器函数。希望这有帮助。