问题描述
在我深入兔子洞之前,我注意到我的TopoJSON中有一个相当奇怪的渲染工件,我不知所措。上面呈现的是在TopoJSON World Atlas repository上找到的官方D3发行版countries-110m.json
。可以看到,俄罗斯北部的部分地区在加拿大北部的上方似乎向左/向右倒转。在我开始制定计划B之前,我的代码中是否有引起这种情况的东西?
async function drawMap() {
map_obj = await getRAWMapData(); // Map topojson
const geojson_obj = topojson.feature(map_obj,map_obj.objects.countries);
var projection = d3.geoIdentity().fitWidth(width,geojson_obj).reflectY(true); // Map Projection
var path = d3.geoPath().projection(projection);
paths = SVGmap.selectAll('path').data(geojson_obj.features).enter().append('path');
paths
.attr('d',path)
.attr('fill','#ddd')
.attr('stroke','white')
.attr('stroke-linejoin','round');
}
drawMap();
解决方法
问题
您正在使用球形数据并将其绘制在平面上(具有d3.geoIdentity),就像数据是平面的一样。
俄罗斯在西半球拥有部分领土-人造物是从远东延伸到远西的路径渲染器,并且在绘制俄罗斯时路径数据越过反子午线时再次延伸。身份转换不会“知道”它应该包裹在一个球体后面-您只是在获取经度和纬度,并将其在屏幕上拉伸,就好像它是2D数据一样。
D3.geoIdentity()拟合方法仅可操纵数据的缩放和平移-无法说明数据的反子午线或地理投影。
解决方案
使用投影-D3地理投影使用球面数学-它们剪切了与反子午线交叉的特征(在本例中为东西向180度)。在这种情况下,俄罗斯将包括两个路径要素:一个在西方,一个在东方。这样可以消除因将两个零件连接到一个零件所需的拉伸而导致的假象。
因此,如果要保持plate carrée的外观,可以使用:
var projection = d3.geoEquirectangular().fitWidth...
任何D3投影都可以使用,d3.geoMercator在外观方面可能会更熟悉。
另一种解决方案是找到已经在反子午线上切过的预投影几何-但是此选项的灵活性远不如使用D3地理投影来投影数据。