我使用Overlay创建标绘操作的小方块元素,如下代码和如图。
然后我监听小方块的mousedown事件。用原始的事件监听:
element.addEventListener('mousedown',process_mousedown);
然后监听map的pointermove
事件
this.map.on('pointermove',process_pointmove)
内部逻辑不用管。pc端测试,process_mousedown
和process_pointmove
两个函数都能触发。逻辑可以正常写。
ok。换移动端。当然mousedown要添加额外的事件。
element.addEventListener('mousedown touchstart',process_mousedown);
测试,发现process_mousedown
函数可以正常触发。但是process_pointmove
这个函数却怎么也触发不了。
跟踪Openlayers的源码。找到ol.map内分发事件的handleMapBrowserEvent
,发现了这样一段代码。
handleMapBrowserEvent(mapBrowserEvent) {
//--还有其他逻辑
let target = mapBrowserEvent.originalEvent.target;
while (target instanceof HTMLElement) {
if (target.parentElement === this.overlayContainerStopEvent_) {
return;
}
target = target.parentElement;
}
//--事件往上层分发
}
我们都知道。当OverLay 不设置stopEvent
属性时,默认该属性为true。即所有overlay都放在ol-overlaycontainer-stopevent
这个div内
图上红色的就是我的那两个控制点的元素。
也就是这个代码逻辑就是,当我事件触发到map层的时候,我判断这个事件的源头元素,如果这个源头元素是我这个ol-overlaycontainer-stopevent
div下面的,则屏蔽所有的事件。你不管在map层用on
监听什么事件,只要这个事件触发的源头是这个div下面的。你都监听不到。
为什么pc端可以?因为pc端的pointermove
源头元素都不是我的那个控制点DIV。但是对于移动端,因为我是按住这个控制点DIV进行拖动,所以源头元素就是我的这个控制点DIV,所以被屏蔽了。
我觉得这是Openlayer这块逻辑有问题,想屏蔽,pc的确没有屏蔽。不想屏蔽,移动端的却屏蔽了。
通过设置overlay的属性stopEvent
为false,可以暂时解决这个问题。因为我的控制点被放到map内部的ol-overlaycontainer
容器中去了。pointermove
事件的源头也找不到我的控制点。所以没有被屏蔽掉。
大家看到这里应该可以了。但是我的问题还没有解决。这样干之后,我通过原生的dom监听的mousedown
和touchstart
事件居然不触发了。先记录到这里,我还得继续解决…
问题解决了。我不能通过设置stopEvent
为false解决问题。因为一旦设置了这个,我移动端pc端不管怎么监听都无法拿到我要点击的那个控制div。因为ol-overlaycontainer-stopevent
永远盖在ol-overlaycontainer
之上。事件都是从ol-overlaycontainer-stopevent
传递出去的。
于是我只能想办法不通过map的那个有问题的函数handleMapBrowserEvent
,并且能够监听pointmove
事件。注意 openlayer官档没有提到map内部事件监听器MapBrowserEventHandler
。其实这个是事件原始分发过来的地方。即我直接监听这个对象。查找源码,发现在map对象中果真有该对象:
该对象内部有个_listerer的map表记录了所有的注册的监听器:
发现其继承自ol.Event.Target
,ol.Event.Target
继承自ol.Disposable
自然找到了操作该监听器的方法:
于是解决方案:
map.mapBrowserEventHandler_.addEventListener('pointermove', xxx);
map.mapBrowserEventHandler_.removeEventListener('pointermove', xxx);
最终测试。完美解决。
注意,上面的removeEventListener
的第二个参数(即绑定的函数)一定要存在,并且这个函数移除之后一定不能再次传递进来。
不信大家看源码~~~这不得不吐槽了。
当listener传递空值的时候。openlayer会检测是否在列表中存在。即使不存在,也是直接执行splice(-1,1)啊。理所当然的,系统监听的函数就会被移除,导致map对应的监听器被干掉。。。。。。慎用啊。