我有一张显示运输路线的d3地图。这些线作为我使用投影和d3路径绘制的坐标列表提供。很正常的东西。问题是,如果我希望路径从例如-179°E到+ 179°E,会发生什么。不幸的是,它越过地图。有什么方法可以使其偏离地图左侧并重新出现在地图右侧?

最佳答案

如果在绘制连接点的线之前使用投影来绘制点(使用svg点的数组),则在穿过反子午线时,该线的行为将不理想。毕竟,您只是在二维网格上绘制点并将它们连接起来,就好像它们是二维网格上的点一样。

但是,如果使用geoPath(使用长而短的点数数组)绘制线,则路径将遵循点之间的最短距离(大圆距)。 geoPath执行3d数学运算,将连接地球仪上的点的路径转换为2d空间中的路径。这意味着


两点之间的直线将成弧形(明显地,如果距离足够远并取决于投影)
倒数无关紧要-大圆距与倒数所在的位置无关
操作地图要容易得多。


您可能已经将geoPath用于背景功能。如果没有,则需要为d3.geoPath()分配一个投影,因为您已经有了一个投影,因此可以使用var path = d3.geoPath().projection(projection)

geoPath需要geojson要素或几何对象。您可以使用以下方法轻松地为一行创建一个:

var coords = [[-179,0],[179,0]];

svg.append("path")
  .datum({ "type": "LineString", "coordinates": coords })


这是一条路径从地图左侧滑落并在右侧重新合并的示例。 (我无法使太平洋轮辋特征足够小,因此我使用了美国并对其进行了旋转,因此它被反子午线切成两半,但它也会切入+/- 180的经度另请参见,在两个或多个点之间绘制geoPath,this):



var width = 500;
var height = 300;

var svg = d3.select("body")
  .append("svg")
  .attr("width",width)
  .attr("height",height);

var projection = d3.geoMercator()
  .rotate([-75,0])
  .scale(50)
  .translate([width/2,height/2]);

var path = d3.geoPath().projection(projection);

var usa = {"type":"FeatureCollection", "features": [
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[-94.81758,49.38905],[-88.378114,48.302918],[-82.550925,45.347517],[-82.439278,41.675105],[-71.50506,45.0082],[-69.237216,47.447781],[-66.96466,44.8097],[-70.11617,43.68405],[-70.64,41.475],[-73.982,40.628],[-75.72205,37.93705],[-75.72749,35.55074],[-81.49042,30.72999],[-80.056539,26.88],[-81.17213,25.20126],[-83.70959,29.93656],[-89.18049,30.31598],[-94.69,29.48],[-99.02,26.37],[-100.9576,29.38071],[-104.45697,29.57196],[-106.50759,31.75452],[-111.02361,31.33472],[-117.12776,32.53534],[-120.36778,34.44711],[-123.7272,38.95166],[-124.53284,42.76599],[-124.68721,48.184433],[-122.84,49],[-116.04818,49],[-107.05,49],[-100.65,49],[-94.81758,49.38905]]],[[[-155.06779,71.147776],[-140.985988,69.711998],[-140.99777,60.306397],[-148.018066,59.978329],[-157.72277,57.570001],[-166.121379,61.500019],[-164.562508,63.146378],[-168.11056,65.669997],[-161.908897,70.33333],[-155.06779,71.147776]]]]},"properties":{"name":"United States of America"},"id":"USA"}
]};

svg.append("path")
      .attr("d",path(usa));

var coords = [[-150,65],[-80,25],[-121,36]];



svg.append("path")
  .datum({ "type": "LineString", "coordinates": coords })
  .attr("fill","none")
  .attr("stroke","steelblue")
  .attr("stroke-width",4)
  .attr("d",path);

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>

09-25 22:28