【问题标题】:How to get click location from custom event handler Leaflet如何从自定义事件处理程序传单中获取点击位置
【发布时间】:2016-10-21 20:54:14
【问题描述】:

我正在尝试为传单中的 CTRL + 单击编写自定义事件处理程序。我的问题是地图给出的点击位置与事件处理程序中的点击位置不同,例如地图点击中的LatLng(51.49174, -0.11639) 在处理程序中变为LatLng(51.50938, -0.126)。如果地图是页面上的唯一内容,则点击位置完全匹配。在地图上方添加一些其他 div 元素(如 <h1> 标题)会使点击不匹配。平移地图也会导致点击位置不匹配。

我想知道我是否正确附加了L.DomEvent.on()。在Leaflet Handlers tutorial 之后,我的代码看起来像

L.CtrlClickHandler = L.Handler.extend({
  addHooks: function() {
    L.DomEvent.on(document, 'click', this._captureClick, this);
  },

  removeHooks: function() {
    L.DomEvent.off(document, 'click', this._captureClick, this);
  },

  _captureClick: function(event) {
    if (event.ctrlKey) {
      console.log('control click registered at layer ' 
        + map.layerPointToLatLng(new L.point(event.layerX, event.layerY)));
    }
  }
});

// add this to all maps
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler);

这是live example on JSFiddle

由于我的代码中存在一些其他依赖项,我正在使用 Leaflet 0.7.7。升级到 Leaflet 1.0.1 可以更好地匹配(例如,LatLng(51.49868, -0.1018)LatLng(51.4987, -0.1018)),但两个位置仍然不完全相同。

我是否将 L.DomEvent 附加到正确的东西上?是否应该以某种方式附加到地图 div,而不是 document

编辑:感谢@AlexParij 的建议。我意识到平移地图也会使点击不匹配,无论地图上方有没有div 元素。 Leaflet 1.0.1 和 0.7.7 都会发生这种情况。我已经尝试了所有我能想到的组合,将不同的事件位置(event.layerXevent.pageXevent.clientXevent.offsetXevent.screenXevent.x)与投影方法layerPointToLatLng 和@987654342 相结合@ 但它们都不匹配地图点击。现在我真的很困惑......摆弄这些不同的选项和 Leaflet 1.0.1:https://jsfiddle.net/c4tkyewz/

【问题讨论】:

  • 我想说看看层点与容器点的方向。 gis.stackexchange.com/questions/69124/…
  • @AlexParij 感谢您的建议。这让我意识到,如果我平移地图,LatLng 对象甚至不会靠近。这适用于地图上方没有任何 div 的情况,对于 Leaflet 0.7.7 或 Leaflet 1.0.1。我尝试了所有我能想到的选项 event.layerXevent.pageXevent.clientXevent.offsetXevent.screenXevent.x,layerPointToLatLngunprojectlayerPointToContainerPoint 结合使用,但没有其中匹配。现在我真的很困惑......摆弄 Leaflet 1.0.1:jsfiddle.net/c4tkyewz

标签: javascript leaflet


【解决方案1】:

TL; DR: 在自定义处理程序中使用map.mouseEventToLatLng()


@AlexParij 是正确的;我没有使用图层点和容器点的正确定义。在处理程序内部,event 与 Leaflet 的内部鼠标事件不同(位置可从e.latlng 获得)。

我查看了 Leaflet 的核心以找到答案。从event 获取位置需要使用鼠标事件 -> 容器点 -> 层点 -> latLng。幸运的是,Leaflet 开发人员已经为此编写了一个很好的函数:mouseEventToLatLng()

/*
 * This is a custom handler to check if someone has control clicked
 * the map and print the location of the click
 */
L.CtrlClickHandler = L.Handler.extend({
  addHooks: function() {
    L.DomEvent.on(document, 'click', this._captureClick, this);
  },

  removeHooks: function() {
    L.DomEvent.off(document, 'click', this._captureClick, this);
  },

  _captureClick: function(event) {
    if (event.ctrlKey) {
      // translate mouse event to lat/lng (note: `mouseEventToLatLng()` 
      // calls Leaflet's `mouseEventToContainerPoint()` followed by 
      // `containerPointToLayerPoint()` and finally `layerPointToLatLng()`)
      var latlng = map.mouseEventToLatLng(event);
      console.log('Handler detected CTRL + click at ' + latlng);
    }
  }
});

// add this to all maps
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler);

Leaflet 1.0.1 的实时示例:https://jsfiddle.net/c4tkyewz/1/

还使用 Leaflet 0.7.7 进行了测试。


作为奖励,要直接从 Leaflet 对单击事件 map.on('click', function(e) {}); 的本机处理访问 CTRL 键,请使用 e.originalEvent.ctrlKey

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    相关资源
    最近更新 更多