OpenLayers2 源码解读 事件Event、Events

OpenLayers.Event就是一个工具类,封装了一些dom事件操作方法,兼容性及操作更好点,比如stop、preventDefault、observe注册事件等等
重点是OpenLayers.Events
//支持的浏览器事件

BROWSER_EVENTS: [
        "mouseover", "mouseout",
        "mousedown", "mouseup", "mousemove", 
        "click", "dblclick", "rightclick", "dblrightclick",
        "resize", "focus", "blur",
        "touchstart", "touchmove", "touchend",
        "keydown"
    ],

很多东西看api、源码注释就了解的差不多了,例如
includeXY: false
注意,这不是经纬度坐标,而是屏幕相对于map的屏幕坐标
源码中解释Should the .xy property automatically be created for browser
* mouse events?//xy属性是否应该包含在event的属性之中;
例如Map.js中

this.events = new OpenLayers.Events(
            this, this.viewPortDiv, null, this.fallThrough, 
            {includeXY: true}
        );

也就是说,map对象的事件中都可以用event.xy获取
具体使用方法看MousePosition.js这个control

this.map.events.register('mousemove', this, this.redraw);//注册mousemove事件
redraw: function(evt) {
        var lonLat;
        if (evt == null) {
            this.reset();
            return;
        } else {
            if (this.lastXy == null ||
                Math.abs(evt.xy.x - this.lastXy.x) > this.granularity ||
                Math.abs(evt.xy.y - this.lastXy.y) > this.granularity)
            {
                this.lastXy = evt.xy;
                return;
            }

            lonLat = this.map.getLonLatFromPixel(evt.xy);
            ...........
       }
    },

什么事件需要自己触发,什么事件需要手动触发(自己写代码)?
大概也能猜到,浏览器事件是不需要自己写的,对,只要是BROWSER_EVENTS事件中的都可以按浏览器事件触发

看initialize构造函数中最后一段

if (element != null) {
    this.attachToElement(element);
}
attachToElement: function (element) {
        ......
        for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {
            type = this.BROWSER_EVENTS[i];
            // register the event cross-browser
            OpenLayers.Event.observe(element, type, this.eventHandler
            );
        .....
    },

就是说,这些事件,你不需要手动触发的,当你绑定一个element时,这些事件也就已经在监听了

浏览器是如何监视和触发事件
注册事件有两种方式:register和on方法
源码中有解释

 events.on({
"loadstart": loadStartListener,
"loadend": loadEndListener,
scope: object
});
// this is equivalent to the following
events.register("loadstart", object, loadStartListener);
 events.register("loadend", object, loadEndListener);

这些事件时如何触发的呢?
还是看Map.js中有这么一段代码:

this.events.triggerEvent("addlayer", {layer: layer});
layer.events.triggerEvent("added", {map: this, layer: layer});

触发事件的方法是triggerEvent,同时需要注意的是,这些自定义的事件需要绑定一个对象,显然不是dom elment,而是这些js对象map、layer等等

triggerEvent: function (type, evt) {
        var listeners = this.listeners[type];
        // fast path
        if(!listeners || listeners.length == 0) {
            return undefined;
        }
        // prep evt object with object & div references
        if (evt == null) {
            evt = {};
        }
        evt.object = this.object;
        evt.element = this.element;
        if(!evt.type) {
            evt.type = type;
        }
        // execute all callbacks registered for specified type
        // get a clone of the listeners array to
        // allow for splicing during callbacks
        listeners = listeners.slice();
        var continueChain;
        for (var i=0, len=listeners.length; i<len; i++) {
            var callback = listeners[i];
            // bind the context to callback.obj
            continueChain = callback.func.apply(callback.obj, [evt]);

            if ((continueChain != undefined) && (continueChain == false)) {
                // if callback returns false, execute no more callbacks.
                break;
            }
        }

它会找到通过listeners找到这个所有的这个事件对应的方法,然后执行
假如注册同一个事件,两次会怎么样呢?
并不会冲突,注册几次执行几次;如果方法返回false,则不会执行其后的事件函数

function init(){
 map = new OpenLayers.Map( 'map');
    layer = new OpenLayers.Layer.OSM( "Simple OSM Map");
    map.addLayer(layer);
    map.setCenter(
        new OpenLayers.LonLat(-71.147, 42.472).transform(
            new OpenLayers.Projection("EPSG:4326"),
            map.getProjectionObject()
        ), 12
    ); 

    map.events.on({"test":testMethod});
    map.events.on({"test":testMethod2});
    map.events.triggerEvent("test", {});
}
function testMethod(){
 alert("testMethod");
//返回false,则后注册的方法不会执行
//return false;
}
function testMethod2(){
 alert("testMethod2");
}

源码

for (var i=0, len=listeners.length; i<len; i++) {
            var callback = listeners[i];
            // bind the context to callback.obj
            continueChain = callback.func.apply(callback.obj, [evt]);

            if ((continueChain != undefined) && (continueChain == false)) {
                // if callback returns false, execute no more callbacks.
                break;
            }
        }

猜你喜欢

转载自blog.csdn.net/u010468602/article/details/51868807