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