您正在查看的投影是Mercator 投影。
对于d3.geoMercator(),比例值源自形成投影表面的圆柱体的圆周。比例值是每弧度的像素数。默认值预计将圆柱体的 360 度拉伸超过 960 个像素:960/Math.PI/2。
对于垂直角距离,没有这样的比例因子,当一个人移动到极端经度时,点之间的角距离越来越大,以至于极点在 y 轴上处于±无穷大。由于这个墨卡托,特别是网络墨卡托经常被截断在 ±~85 度。在 [-180,85] 和 [180,-85] 范围内,墨卡托是正方形的。
此限制已包含在d3-geoMercator 中,它“定义了一个默认的 projection.clipExtent,以便将世界投影到一个正方形,裁剪到大约 ±85° 纬度。(docs)”
这意味着如果我们想要显示 d3-geoMercator 的完整范围,跨越 960 x 960 像素,我们可以使用:
d3.geoMercator()
.scale(960/Math.PI/2) // 960 pixels over 2 π radians
.translate([480,480]) // the center of the SVG/canvas
这给了我们:
d3-geoMercator 的默认中心是 [0°,0°],所以如果我们希望 [0°,0°] 位于 SVG/画布的中间,我们可以平移中心,这样它在中间,翻译为[width/2,height/2]
现在我们展示了整个世界,我们可以改进以只展示我们想要的部分。最简单的方法可能只是从 svg/canvas 底部删除像素。使用上面的代码,画布/svg 高度为 700 像素(并保持 960 像素,使用相同的比例和平移)我得到:
我没有从这张图片中删除南极洲 - 只是碰巧它被切断而无需过滤掉(这不一定是理想的做法:它仍然被绘制)。
因此,宽度为 960、高度为 700、投影比例为 960/Math.PI/2 且平移为 [480,480] 的 SVG/Canvas 似乎没问题。这些值将针对不同的视口大小一起缩放。
对于地图,通常需要大量的眼球才能获得所需的视觉效果,调整 projection.translate() 或 projection.center() 可以帮助将地图移动到所需的位置。但是我们可以通过计算来做到这一点。我将在这里讨论一种方法,使用projection.fitSize()(尽管如果没有额外的步骤,这将无法解决所需的纵横比)。
Project.fitSize([width,height],geojson) 接受一个指定 SVG/canvas 尺寸的数组和一个 geojson 对象,并调整投影比例和平移值,以便 geojson 功能包含在 SVG/canvas 中。 geojson 功能可以是您要显示的世界部分的边界框,因此您可以使用:
projection.fitSize([width,height], {
type: "Polygon",
coordinates: [[
[-179.999,84] ,
[-179.999,-57] ,
[179.999,-57] ,
[179.999,84],
[-179.999,84]
]]
})
北约 84 度是格陵兰岛的北端,南约 56 度大致是南美洲的尖端。这将确保您想要看到的整个世界部分都是可见的。但是,如上所述,这不考虑纵横比,因此如果您将上述范围限制为方形尺寸,您仍将显示墨卡托的完整范围。