Skip to content
目录

事件的派发和传递

在整个地图中,除了少部分用户自定的UIDom事件外,其他的所有的事件的源头都是地图对象,地图是事件的发起者,进过一定逻辑传递到图层和图形要素

主要方法有:

  • on 监听事件
  • off 移除事件
  • once 只监听一次
  • fire 派发事件,一般用不到,除非你写插件或者给图层等自定义事件消息

WARNING

注意图层是没有鼠标交互事件的比如click这种,在maptalks体系内图层是个虚拟的东西的,其用来管理和组织数据的

地图和图形才具有鼠标交互事件

基本用法

js
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导致内部判断他们不相等,所以移除不掉

批量监听事件

js
function mapClickFunc() {}
map.on("click mousemove dblclick", mapClickFunc);
//or
const events = ["click", "mousemove", "dblclick"];
map.on(events.join(" "), mapClickFunc);

阻止事件冒泡

有时我们既监听了地图的事件,也监听了图形的事件,期望的:

  • 图形被点击了不要触发地图的事件
  • 点击了地图的空白地方时触发地图的点击事件
js
function mapClickFunc() {}
map.on("click", mapClickFunc);

point.on("click", (e) => {
    //do somethings
    //阻止事件冒泡,当改图标被点击了,地图就不会触发click事件了
    return false;
});

事件里的属性

事件里主要和常用的属性有

  • coordinate 当前鼠标位置的经纬度坐标
  • containerPoint 当前鼠标位置的屏幕坐标
  • target 事件监听的所属者,地图,图层,图形,UI等,如果是地图的事件其就是地图对象,图形的事件其就是图形
js
map.on("click", function (e) {
    const { coordinate, containerPoint, target } = e;
    console.log(coordinate, containerPoint, target);
});

事件里的this

事件的处理函数的this就是事件监听的所属者,即地图,图层,图形等

WARNING

注意如果事件处理函数使用了箭头函数,this将被改变

js
map.on("click", (e) => {
    console.log(this);
});

事件函数里获取map?

因为用户可能使用箭头函数会导致this被改变,所以不建议用this去获取map

js
point.on("click", (e) => {
    //该代码将报错,提示not find getMap function
    const map = this.getMap();
});

可以使用target对象获取map,其值不会像this那样会被改变

js
point.on("click", function (e) {
    const map = e.target.getMap();
});

WARNING

注意

  • 只有图层,图形,UI元素等事件里可以这样这样处理,地图的事件里因为target就是map本身,是没有getMap方法的

  • 获取的map值可能为空,代码里需要做好兜底处理

所以代码可以这样写,可以兼容地图,图层,图形,UI元素等,确保拿到的一定是地图对象

js
point.on("click", function (e) {
    const target = e.target;
    const map = target.getMap ? target.getMap() : target;
    if (map) {
        //do some thingis
    }
});

UI事件冒泡

maptalks里的UI包括controlui两个部分

  • control 表示控件,其在地图位置是死的,不会随着地图的移动而改变,比如 ZoomControl
  • ui 的元素其位置会随着地图的移动而改变,比如UIMarker
  • control dom元素默认都是禁用冒泡,即这些dom元素被click等是不会触发地图的click
  • ui 元素除了UIMarker也是默认都是禁用冒泡的
  • UIMarker之所以默认支持冒泡因为其比较特殊,其扮演者特殊的point的角色,即当鼠标对其进行移动缩放等 应该触发地图的移动和缩放,故默认放开了冒泡

相关讨论地址

怎样手动控制UI元素是否支持冒泡? UI元素创建是有个参数eventsPropagation用来表示其是否支持冒泡, 业务里请根据自己的需要设置合适的值

js
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 });

This document is generated by mdpress