......................................................

...........................................................................................................................

导航

OpenLayers中对 Map的事件 的使用和分析

Posted on 2009-04-07 14:22  asdfdfasdfasf  阅读(5987)  评论(11编辑  收藏  举报

Map这个类提供了很多的事件可以让我们使用,本文说的就是如何使用以及对这部分源代码分析,关于openlayers的事件网上有很多的分析。


如何使用:
var map;
// define custom map event listeners
                function mapEvent(event) {
                    log(event.type);
                }
                function mapBaseLayerChanged(event) {
                    log(event.type + " " + event.layer.name);
                }
                function mapLayerChanged(event) {
                    log(event.type + " " + event.layer.name + " " + event.property);
                }
                map = new OpenLayers.Map('map', {
                    eventListeners: {
                        "moveend": mapEvent,
                        "zoomend": mapEvent,
                        "changelayer": mapLayerChanged,
                        "changebaselayer": mapBaseLayerChanged
                    }
                });
                即,初始化的时候传入map的构造函数一个object,这个object中有个属性:
                eventListeners【其实是个哈希表】
看来我们要看map类的构造函数了。
---------------------------------------------------------------------------
---------------------------------------------------------------------------
进入map类,看构造函数
    /**
     * Constructor: OpenLayers.Map
     * Constructor for a new OpenLayers.Map instance.
     *
     * Parameters:
     * div - {String} Id of an element in your page that will contain the map.
     * options - {Object} Optional object with properties to tag onto the map.
     *
     * Examples:
     * (code)
     * // create a map with default options in an element with the id "map1"
     * var map = new OpenLayers.Map("map1");
     *
     * // create a map with non-default options in an element with id "map2"
     * var options = {
     *     maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),
     *     maxResolution: 156543,
     *     units: 'm',
     *     projection: "EPSG:41001"
     * };
     * var map = new OpenLayers.Map("map2", options);
     * (end)
     */   
    initialize: function (div, options)
    构造函数中进行初始化
    首先有一句:
            // now override default options
        OpenLayers.Util.extend(this, options);
        Util.extend函数的作用可以理解为:是把第二个参数的属性方法都传给第一个参数
        现在我们看刚才传入的带有eventListeners属性的object
        我们传入的object给了options,则object中的eventListeners就传给了this.eventListeners
        就是map类中的eventListeners属性
    来看这个属性的定义:
       /**
     * APIProperty: eventListeners
     * {Object} If set as an option at construction, the eventListeners
     *     object will be registered with <OpenLayers.Events.on>.  Object
     *     structure must be a listeners object as shown in the example for
     *     the events.on method.
     */
    eventListeners: null,
注释中说这个属性中的东西将通过OpenLayers.Events.on注册上,等会再说
同时指出这个对象必须是个“listeners object”的结构,其实就是我们前面传入的参数的eventListeners的结构
!!这里要注意了,listeners object是整个事件机制中的核心,所有的事件都是注册到他里面,然后触发的时候也是查找这个listeners object,找到里面注册的函数然后执行
goon..

构造函数中下面开始在map中初始化自己的events属性:
this.events = new OpenLayers.Events(this,
                                            this.div,
                                            this.EVENT_TYPES,
                                            this.fallThrough,
                                            {includeXY: true});
再往下就注册了:
if(this.eventListeners instanceof Object) {
            this.events.on(this.eventListeners);
        }
通过map自己的Events属性(其实也是个object,就是events类的实例)中的on这个函数注册上,
我们要进入OpenLayers.Events类
---------------------------------------------------------------------------
---------------------------------------------------------------------------
看这个on方法
   /**
     * Method: on
     * Convenience method for registering listeners with a common scope.
     *
     * Example use:
     * (code)
     * events.on({
     *     "loadstart": loadStartListener,
     *     "loadend": loadEndListener,
     *     scope: object
     * });
     * (end)
     */
    on: function(object) {
        for(var type in object) {
            if(type != "scope") {
                this.register(type, object.scope, object[type]);
            }
        }
    },
on这个函数参数还是第一步中我们传入的eventListeners,就是那个哈希表
遍历,这个“scope”键值是事件的“产生源”对象,就是这个键值对应的对象触发我们注册的事件
register(type, object.scope, object[type])
type就是事件名称
object[type]就是处理事件的函数名
可以看一下第一步中传入的参数:
eventListeners: {
                        "moveend": mapEvent,
                        "zoomend": mapEvent,
                        "changelayer": mapLayerChanged,
                        "changebaselayer": mapBaseLayerChanged
                    }
再进入events类的另一个函数:this.register(type, object.scope, object[type])
   /**
     * APIMethod: register
     * Register an event on the events object.
     *
     * When the event is triggered, the 'func' function will be called, in the
     * context of 'obj'. Imagine we were to register an event, specifying an
     * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the
     * context in the callback function will be our Bounds object. This means
     * that within our callback function, we can access the properties and
     * methods of the Bounds object through the "this" variable. So our
     * callback could execute something like:
     * :    leftStr = "Left: " + this.left;
     *  
     *                   or
     * 
     * :    centerStr = "Center: " + this.getCenterLonLat();
     *
     * Parameters:
     * type - {String} Name of the event to register
     * obj - {Object} The object to bind the context to for the callback#.
     *                     If no object is specified, default is the Events's
     *                     'object' property.
     * func - {Function} The callback function. If no callback is
     *                        specified, this function does nothing.
     *
     *
     */
    register: function (type, obj, func) {

        if ( (func != null) &&
             (OpenLayers.Util.indexOf(this.eventTypes, type) != -1) ) {

            if (obj == null)  {
                obj = this.object;
            }
            var listeners = this.listeners[type];
            listeners.push( {obj: obj, func: func} );
        }
    },
到这里,我们能看到我们所说的核心,那个哈希表,把自己的值都赋给了events类的一个属性:listeners
  /**
     * Property: listeners
     * {Object} Hashtable of Array(Function): events listener functions 
     */
    listeners: null,

这个事件机制的核心哈希表,键名就是事件的名称,也就是参数中的type,键值是一个对象{obj: obj, func: func}
当然这个对象中还有对象。。。。

现在事件已经注册上了,还有一个问题,register函数中提到了this.eventTypes,this.object
所以我们再回来看下events类的构造函数。
map类中实例化events属性的情景:
this.events = new OpenLayers.Events(    this, //指的是map
                                            this.div,
                                            this.EVENT_TYPES,
                                            this.fallThrough,
                                            {includeXY: true});
我们可以和events类的构造函数对比一下参数,就会明白了 
   /**
     * Constructor: OpenLayers.Events
     * Construct an OpenLayers.Events object.
     *
     * Parameters:
     * object - {Object} The js object to which this Events object  is being
     * added element - {DOMElement} A dom element to respond to browser events
     * eventTypes - {Array(String)} Array of custom application events
     * fallThrough - {Boolean} Allow events to fall through after these have
     *                         been handled?
     * options - {Object} Options for the events object.
     */
    initialize: function (
                   object,
                   element,
                   eventTypes,
                   fallThrough,
                   options)
      {
        OpenLayers.Util.extend(this, options);
        this.object     = object;
        this.element    = element;
        this.fallThrough = fallThrough;
        this.listeners  = {};

        // keep a bound copy of handleBrowserEvent() so that we can
        // pass the same function to both Event.observe() and .stopObserving()
        this.eventHandler = OpenLayers.Function.bindAsEventListener(
            this.handleBrowserEvent, this
        );

        // if eventTypes is specified, create a listeners list for each
        // custom application event.
        this.eventTypes = [];
        if (eventTypes != null) {
            for (var i=0, len=eventTypes.length; i<len; i++) {
                this.addEventType(eventTypes[i]);
            }
        }
       
        // if a dom element is specified, add a listeners list
        // for browser events on the element and register them
        if (this.element != null) {
            this.attachToElement(element);
        }
    },
 上面events的初始化是发生在map的初始化中,this.events.on(this.eventListeners);之前的,所以上面提到的register函数中的this.eventTypes,this.object 就明确意思了:
 this.object(this是指的events类)就是map,也就是说map是我们第一步传入参数中的注册事件的“发生源”,(比如button是onclik的“发生源”,“发生源”是本人自定义的。。不知道是否有合适的称呼,术语应该就是srcElement)
this.eventTypes(this是指的events类)就是map类中定义的一个常量:this.EVENT_TYPES(this是指的map类)
查到map类中的这个常量 EVENT_TYPES: [
        "preaddlayer", "addlayer", "removelayer", "changelayer", "movestart",
        "move", "moveend", "zoomend", "popupopen", "popupclose",
        "addmarker", "removemarker", "clearmarkers", "mouseover",
        "mouseout", "mousemove", "dragstart", "drag", "dragend",
        "changebaselayer"],
所以我们在初始化map的时候传入的参数中,注册的事件都是来自于这个常量中的