如何从自定义事件处理程序Leaflet

时间:2016-10-20 14:54:12

标签: javascript leaflet

我试图在Leaflet中为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.screenX和{ {1}})使用投影方法event.xlayerPointToLatLng,但它们都不匹配地图点击。现在我真的很困惑......摆弄这些不同的选项和Leaflet 1.0.1:https://jsfiddle.net/c4tkyewz/

1 个答案:

答案 0 :(得分:1)

<强> TL; DR:在自定义处理程序中使用componentWillReceiveProps()

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

我查看了Leaflet的核心以找到答案。从e.latlng获取位置需要参加鼠标事件 - &gt;容器点 - &gt;层点 - &gt;的latLng。值得庆幸的是,Leaflet开发人员已经为此编写了一个很好的函数:event

mouseEventToLatLng()

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

还使用Leaflet 0.7.7进行测试。

<小时/> 作为奖励,要直接从Leaflet本机处理点击事件/* * 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); 访问CTRL键,请使用map.on('click', function(e) {});