如何在 D3 地图中重绘标签?

How redraw labels in D3 maps?

我正在按照两个教程在 TOPOJson 中制作地图:

  1. 显示国家、边界和城市(点和标签)。 Tutorial here.
  2. 移动和缩放地图。 Tutorial here.

我可以显示平移、平移、缩放,但城市名称没有重绘。

       var path = d3.geo.path()
      .projection(projection)
      .pointRadius(2);

  /* What's hapenning here ? */
  var svg = d3.select("#vis").append("svg:svg")
      .attr("width", width)
      .attr("height", height)
      .call(d3.behavior.zoom().on("zoom", redraw));

  /* Format projected 2D geometry appropriately for SVG or Canvas. */
  d3.json("uk.json", function(error, uk) {
    svg.selectAll(".subunit")
        .data(topojson.feature(uk, uk.objects.subunits).features)
      .enter().append("path")
        .attr("class", function(d) { return "subunit " + d.id; })
        .attr("d", path);

    svg.append("path")
        .datum(topojson.mesh(uk, uk.objects.subunits, function(a, b) { return a !== b && a.id !== "IRL"; }))
        .attr("d", path)
        .attr("class", "subunit-boundary");

    svg.append("path")
        .datum(topojson.mesh(uk, uk.objects.subunits, function(a, b) { return a === b && a.id === "IRL"; }))
        .attr("d", path)
        .attr("class", "subunit-boundary IRL");

    svg.append("path")
      .datum(topojson.feature(uk, uk.objects.places))
      .attr("d", path)
      .attr("class", "place");

    svg.selectAll(".place-label")
        .data(topojson.feature(uk, uk.objects.places).features)
      .enter().append("text")
        .attr("class", "place-label")
        .attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; })
        .attr("x", function(d) { return d.geometry.coordinates[0] > -1 ? 6 : -6; })
        .attr("dy", ".35em")
        .style("text-anchor", function(d) { return d.geometry.coordinates[0] > -1 ? "start" : "end"; })
        .text(function(d) { return d.properties.name; });

    svg.selectAll(".subunit-label")
      .data(topojson.feature(uk, uk.objects.subunits).features)
    .enter().append("text")
      .attr("class", function(d) { return "subunit-label " + d.id; })
      .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .text(function(d) { return d.properties.name; });
  });

  function redraw() {
    // d3.event.translate (an array) stores the current translation from the parent SVG element
    // t (an array) stores the projection's default translation
    // we add the x and y vales in each array to determine the projection's new translation
    var tx = t[0] * d3.event.scale + d3.event.translate[0];
    var ty = t[1] * d3.event.scale + d3.event.translate[1];
    projection.translate([tx, ty]);

    // now we determine the projection's new scale, but there's a problem:
    // the map doesn't 'zoom onto the mouse point'
    projection.scale(s * d3.event.scale);

    // redraw the map
    svg.selectAll("path").attr("d", path);

    // redraw the labels
    svg.selectAll(".place-label");

    // redraw the x axis
    xAxis.attr("x1", tx).attr("x2", tx);

    // redraw the y axis
    yAxis.attr("y1", ty).attr("y2", ty);
  }

我尝试添加这一行:

svg.selectAll(".place-label").attr("d", path);

在重绘功能中,但没有成功。

你能告诉我应该添加哪一行来刷新他们的位置吗?

这是我的实时代码:Plunker live example & code

要使标签随地图一起移动,您需要执行以下操作: 在 redraw function

  svg.selectAll(".place-label")[0].forEach( function(d){
    var data = d3.select(d).data()[0];//this will give you the text location data
    d3.select(d).attr("transform", "translate("+projection(data.geometry.coordinates)+")" )//pass the location data here to get the new translated value.
  });

对于子单元做:

svg.selectAll(".subunit-label")
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })

工作示例here

希望这有效!