使用 d3.behavior.drag() 平移地图

Using d3.behavior.drag() to pan a map

本文关键字:地图 d3 behavior drag 使用      更新时间:2023-09-26

我在地图上应用 D3 的 behavior.drag() 时遇到了一些问题。在此示例中,拖动地图会导致非常快速的平移,并且单击的点不会停留在鼠标上 - http://bl.ocks.org/jczaplew/6453048

我的拖动行为代码如下所示 -

var drag = d3.behavior.drag()
  .origin(function() { return {x: rotate[0], y: -rotate[1]}; })
  .on("drag", function() {
    rotate[0] = d3.event.x;
    rotate[1] = -d3.event.y;
   // Refresh the map
    projection.rotate(rotate);
    path = d3.geo.path().projection(projection);
    d3.selectAll("path").attr("d", path);
});

我需要什么:

  1. 平移而不翻译整个 SVG。平移地图的功能(此问题中表达的问题 - 使用 d3 缩放和平移以太平洋为中心的墨卡托地图.js并在此示例中演示 - http://bl.ocks.org/d3noob/4966228)是不可取的。
  2. 当用户单击并拖动地图
  3. 时,单击的点会粘在光标上(即单击并拖动西班牙会围绕西班牙旋转地图)

怀疑这个问题与drag.origin()有关,但也许我根本不应该使用d3.behavior.drag()?非常感谢任何和所有帮助!

我想我找到了一个潜在的(尽管有点不令人满意)的答案。使用此示例中的逻辑(http://mbostock.github.io/d3/talk/20111018/azimuthal.html),我创建了这个 - http://bl.ocks.org/jczaplew/6457917

关键位是跟踪拖动开始的位置(即用户单击时)。所需旋转的经度和经度的逻辑为

开始投影旋转 + (开始屏幕位置 - 目标屏幕位置)/4

拖动行为现在看起来像这样

    var drag = d3.behavior.drag()
        .on("dragstart", function() {
          var proj = projection.rotate();
          m0 = [d3.event.sourceEvent.pageX, d3.event.sourceEvent.pageY];
          o0 = [-proj[0],-proj[1]];
        })
       .on("drag", function() {
         if (m0) {
           var m1 = [d3.event.sourceEvent.pageX, d3.event.sourceEvent.pageY],
               o1 = [o0[0] + (m0[0] - m1[0]) / 4, o0[1] + (m1[1] - m0[1]) / 4];
           projection.rotate([-o1[0], -o1[1]]);
         }
      // Update the map
        path = d3.geo.path().projection(projection);
        d3.selectAll("path").attr("d", path);
    });

这仍然感觉很黑客,而且似乎不能很好地扩展。例如,更改投影和投影比例似乎需要将所需旋转坐标的归一化从 4 调整为其他值,以实现相同的平滑度和行为。

有人有其他想法吗?我很想看到其他更优雅的方式来完成此功能。