在Leaflet上检测用户发起的平移/缩放操作

19
我有一个用于位置共享的 Leaflet 地图。当用户分享他们的位置时,会在地图上添加一个标记以供其他用户查看。每当添加、移动或删除标记时,它会自动调整地图以显示所有标记。我还添加了一个自定义控件,可以切换自适应行为。这一切都很好,但我还想让地图变得更智能,能够在用户平移或缩放地图时自动关闭自适应行为。
这实际上相当困难,因为我无法找到一个好的方法来区分用户还是自动适配所引起的平移/缩放操作。我最初是监听 panstart 和 zoomstart 事件,但这些事件也会被自适应所触发。我想设置一个标志,告诉它在自适配引起的缩放/平移时不要关闭自适应。我先检查这个标志,然后在收到 panstart 和 zoomstart 后才关闭自适应,并在收到 panend 和 zoomend 时清除它。
这似乎可以正常工作,直到发生一个不导致平移或缩放的自适应。假设我们有一个大的自适应聚类标记,并且其中一个标记被移除。由于边界框没有改变,因此不会触发平移或缩放,因此告诉它不要关闭自适应的标志永远不会被清除。用户下次平移或缩放地图时,它不会像应该一样关闭自适应,因为它认为仍处于自适应操作中。 我该如何可靠地在用户直接平移或缩放地图时关闭自适应,但在其他情况下保留它? 以下是相关代码:
var markers = [];        // Map markers are stored in this array.
var autoFit = true;      // Whether auto-fit is turned on
var lockAutoFit = false; // Temporarily lock auto-fit if true
var map;                 // Leaflet map object

function initMap() {
    // Leaflet map initialized here
    map.on('movestart zoomstart', function() {
        if (!lockAutoFit) {
            autoFit = false;
        }
    });
    map.on('moveend zoomend', function() {
        lockAutoFit = false;
    });
}

function toggleAutoFit() {
    autoFit = !autoFit;

    if (autoFit) {
        lockAutoFit = true;
        fitMap();
    }
}

function addOrUpdateMarker(marker, coords) {
    lockAutoFit = true;
    // do the marker update here
    fitMap();
}

function removeMarker(marker) {
    lockAutoFit = true;
    // remove the marker here
    fitMap();
}

// Pans and zooms the map so that all markers fit in the map view.
// Invoked whenever a marker is added, moved or deleted, or when
// the user turns on auto-fit.
function fitMap() {
  if (!autoFit || !markers.length) {
    return;
  }

  map.fitBounds(new L.featureGroup(markers).getBounds());
}
4个回答

10

最后我在我的fitBoundssetView方法调用周围设置了一个标志,例如:

isProgramaticZoom = true
map.fitBounds(new L.featureGroup(markers).getBounds());
isProgramaticZoom = false

然后关闭自适应布局的代码:

map.on('zoomstart', function() {
  if (!isProgramaticZoom) {
    //turn off auto-fit
  }
})

map.on('dragstart', function() {
  //turn off auto-fit
})

很不幸,仍然不理想但应该能解决问题


需要在下一帧动画之后安排重置标志,这是实际边界发生变化和触发缩放事件的时候。 - Brendan Heywood

1

编辑:显然已被删除,不再起作用

这是一个旧问题,但我最近发现它,认为它仍然足够相关,值得给出解决方案。

我遵循了这个解决方案:Leaflet用户触发事件

其中使用了:

map.on('dragstart', function (e) {
    if (e.hard) {
        // moved by bounds
    } else {
       // moved by drag/keyboard
    }
});

这里的解决方案是未记录的e.hard部分;评论已经说明了问题。
或者,您可能想使用moveend而不是dragstart

2
这个未记录的标记已经从Leaflet核心完全删除,因此不再起作用。 - Brendan Heywood
@Wayneio 这个方法不再有效 - Majid Hojati

0

你可以使用drag、dragstart、dragend事件来实现地图平移。至于地图缩放,我认为没有类似的事件。


是的,我知道拖动的那些,但正如你所说,没有类似缩放的东西,所以它不幸地并没有真正解决我的问题。 - Robert J. Walker

-1

6
请核对源代码:实际上,我的代码中使用了缩放事件。问题在于,这些事件会在用户手动缩放和自适应缩放时同时触发。目前我无法可靠地确定事件是由用户操作控件触发还是由自适应缩放操作触发的。这就是我正在努力解决的问题。 - Robert J. Walker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接