事件的派发和传递
在整个地图中,除了少部分用户自定的UIDom事件外,其他的所有的事件的源头都是地图对象,地图是事件的发起者, 经过一定逻辑传递到图层和图形要素
主要方法有:
- on 监听事件
- off 移除事件
- once 只监听一次
- fire 派发事件,一般用不到,除非你写插件或者给图层等自定义事件消息
WARNING
如果你真的需要给Map/Layer/Geometry等自定义事件(fire),请慎重定义事件的名字,否则可能导致和地图里默认 事件重复从而导致出现一些意外的情况
WARNING
注意图层是没有鼠标交互事件的比如click这种,在maptalks体系内图层是个虚拟的东西的,其用来管理和组织数据的
地图和图形才具有鼠标交互事件
基本用法
function mapClickFunc() {}
map.on("click", mapClickFunc);
//remove click event
map.off("click", mapClickFunc);
//测试匿名函数
map.on("click", (e) => {});
//不能移除上面的监听的函数,正确的方式是上面的把监听函数提出个独立的函数
map.off("click", (e) => {});
layer.on("visiblechange", (e) => {});
point.on("click", (e) => {});
WARNING
要想移除一个事件监听时,必须保证监听和移除的函数是同一个,匿名函数是不行的,匿名函数每次相当于new 了个Function,而事件内部处理会严格判断函数是否相等,因为每次都是new Function导致内部判断他们不相等,所以移除不掉
批量监听事件
function mapClickFunc() {}
map.on("click mousemove dblclick", mapClickFunc);
//or
const events = ["click", "mousemove", "dblclick"];
map.on(events.join(" "), mapClickFunc);
阻止事件冒泡
有时我们既监听了地图的事件,也监听了图形的事件,期望的:
- 图形被点击了不要触发地图的事件
- 点击了地图的空白地方时触发地图的点击事件
function mapClickFunc() {}
map.on("click", mapClickFunc);
point.on("click", (e) => {
//do somethings
//阻止事件冒泡,当改图标被点击了,地图就不会触发click事件了
return false;
});
事件里的属性
事件里主要和常用的属性有
coordinate
当前鼠标位置的经纬度坐标containerPoint
当前鼠标位置的屏幕坐标target
事件监听的所属者,地图,图层,图形,UI等,如果是地图的事件其就是地图对象,图形的事件其就是图形
map.on("click", function (e) {
const { coordinate, containerPoint, target } = e;
console.log(coordinate, containerPoint, target);
});
事件里的this
事件的处理函数的this
就是事件监听的所属者,即地图,图层,图形等
WARNING
注意如果事件处理函数使用了箭头函数,this将被改变
map.on("click", (e) => {
console.log(this);
});
事件函数里获取map?
因为用户可能使用箭头函数会导致this
被改变,所以不建议用this
去获取map
point.on("click", (e) => {
//该代码将报错,提示not find getMap function
const map = this.getMap();
});
可以使用target
对象获取map,其值不会像this
那样会被改变
point.on("click", function (e) {
const map = e.target.getMap();
});
WARNING
注意
只有图层,图形,UI元素等事件里可以这样这样处理,地图的事件里因为target就是map本身,是没有getMap方法的
获取的map值可能为空,代码里需要做好兜底处理
所以代码可以这样写,可以兼容地图,图层,图形,UI元素等,确保拿到的一定是地图对象
point.on("click", function (e) {
const target = e.target;
const map = target.getMap ? target.getMap() : target;
if (map) {
//do some thingis
}
});
UI事件冒泡
maptalks里的UI包括control
和ui
两个部分
- control 表示控件,其在地图位置是死的,不会随着地图的移动而改变,比如
ZoomControl
等 - ui 的元素其位置会随着地图的移动而改变,比如
UIMarker
- control dom元素默认都是禁用冒泡,即这些dom元素被
click
等是不会触发地图的click
- ui 元素除了
UIMarker
也是默认都是禁用冒泡的 UIMarker
之所以默认支持冒泡因为其比较特殊,其扮演者特殊的point
的角色,即当鼠标对其进行移动缩放等 应该触发地图的移动和缩放,故默认放开了冒泡
怎样手动控制UI元素是否支持冒泡? UI元素创建是有个参数eventsPropagation
用来表示其是否支持冒泡, 业务里请根据自己的需要设置合适的值
var dom = document.createElement("div");
dom.innerHTML = "hello ui marker";
var marker = new maptalks.ui.UIMarker([0, 0], {
eventsPropagation: false,
draggable: true,
content: dom,
}).addTo(map);
// update options config
// marker.config({ eventsPropagation: true });