我正在做一个可以旋转的地球仪。我需要将国家和土地放在一起(是的,我知道,我只能使用国家,但我需要两者都使用)。但是如果我那样做,土地就会消失,我也不知道怎么了。但是,如果我注释“国家!”,则此代码将完美运行。
这是第一次使用它,也许我对topojson有错误?

var path = d3.geoPath().projection(projection);
svg.append("path").datum(graticule).attr("class", "graticule").attr("d", path);

//Land
d3.json("https://rawgit.com/jonataswalker/map-utils/master/data/json/world-110m.json", function(error, topo) {
  if (error) throw error;
  var land = topojson.feature(topo, topo.objects.land);
      svg.selectAll("path.foreground").data([land]).enter().append("path").attr("d", path).attr("class", "foreground");
});

//Countries!
d3.json("https://rawgit.com/Bramsiss/Globe/master/world-counries.json", function(collection) {
var countries = svg.selectAll("path").data(collection.features).enter().append("path").attr("d", path).attr("class", "country");
});

//drag
var λ = d3.scaleLinear().domain([0, width]).range([-180, 180]);
var φ = d3.scaleLinear().domain([0, height]).range([90, -90]);
    var drag = d3.drag().subject(function() {
        var r = projection.rotate();
        return {
      x: λ.invert(r[0]),
      y: φ.invert(r[1])
    };
  }).on("drag", function() {
    projection.rotate([λ(d3.event.x), φ(d3.event.y)]);
    svg.selectAll(".foreground").attr("d", path);
  });
  svg.call(drag);

最佳答案

问题出现在这里:

svg.selectAll("path")
   .data(collection.features)
   .enter().append("path")
   .attr("d", path)
   .attr("class", "country");
  });


svg.selectAll(“ path”)选择一个现有路径-世界轮廓。因此,您的回车选择不包括第一个路径-它已被附加。它是更新选择的一部分。您确实使用此代码设置了第一个路径的原点,但未更新其形状。

如果仔细看,安哥拉的边界比海港的边界要浅,这是因为边界由两条线组成,而不是两条线(两个国家的边界​​)。

由于您仅使用Enter来创建和塑造新元素,因此地球土地的原始轮廓不变。但是,当您使用更新选择旋转地球时:

svg.selectAll(".foreground, .country").attr("d", path);


您可以根据添加国家/地区时附加的数据来更新所有路径的形状。由于您将绑定到DOM中第一条路径(地球的轮廓)的数据替换为国家/地区数据数组中第一项的数据,因此将根据新数据重绘该路径。

这就是为什么如果拖动地球,安哥拉的边界会发生变化,如果您查看DOM,也会注意到该国家的类别为“前景”,而不是“国家”。

解:

使用空选择附加国家/地区:

svg.selectAll(null)


要么

svg.selectAll()


要么

svg.selectAll(".country")  // since there are no elements with this class yet.


这是updated pen

07-24 17:10