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的时候传入的参数中,注册的事件都是来自于这个常量中的