百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:

原文:百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:
 

百度地图API详解之事件机制

2011年07月26日 星期二 下午 04:06

和DOM编程里的事件模型一样,百度地图API也提供了类似的事件机制。本文介绍了事件监听的添加和移除方法,this指针和事件参数的使用以及绑定事件监听函数中涉及的闭包问题,最后分享了一个用来增强地图API事件机制的开源项目。


事件添加和移除

我们最简单的事件开始,下面的代码示例给map对象添加了click事件的监听函数,当用户点击地图时该监听函数就会被触发:

var map
=new BMap.Map('map');
map.centerAndZoom(new BMap.Point(116.404,
39.915),
11);

map.addEventListener('click',
function(){
alert('您点击了地图');
});

在初始化地图完成后,我们通过map对象的addEventListener方法添加click事件的监听。凡是在类参考文档中说明某个类具备某些事件时,我们都可以调用该对象的addEventListener方法添加响应的事件监听函数。

上面我们通过传入一个匿名函数添加了事件监听,如果我们需要移除事件监听,则需要将监听函数用具名函数表示:

var clickHandler
=function(){
alert('您点击了地图');
}

map.addEventListener('click', clickHandler);

// 后续进行移除
map.removeEventListener('click', clickHandler);


事件参数

和DOM事件类似,在百度地图API的事件机制中也提供了事件参数,参数通过监听函数的参数进行传递,比如我们修改最开始的代码:

map.addEventListener('click',
function(e){
alert('点击坐标:
'+ e.point.lng
+',
'+ e.point.lat);
});

通过API的类参考文档得知,click事件的参数包含type、target、point和pixel四个属性,上面的示例就是获取了point属性,它表示当前点击的地理位置。


this

在事件监听中还可以通过this引用触发事件的对象,就像标准的DOM事件一样。

map.addEventListener('dragend',
function(e){
alert(this.getCenter());
// 这里的this就是map实例
});


事件闭包

闭包是Javascript脚本语言的特性之一,不熟悉它的开发者很可能犯下面这种错误:页面有十个标注(Marker实例),我希望点击不同的标注开启内容不同的信息窗口,每个信息窗口显示该标注的索引(1到10)。首先我们初始化标注实例并存放于数组中:

var markers
= [];
for (var i
=0; i
<10; i
++) {
var mkr
=new BMap.Marker(new BMap.Point(116.2+
i /20,
39.855), {title: i
+1});
markers.push(mkr);
map.addOverlay(mkr);
}

我们给每个标注添加自己的title属性以示区分,你将看到如下效果:

下面,我们添加标注的点击事件,用来开启内容不同的信息窗口:

for (i
=0; i
<10; i
++) {
markers[i].addEventListener('click',
function(){
this.openInfoWindow(new BMap.InfoWindow('我是第'+
(i +1)
+'个标注'));
});
}

代码看起来没有任何问题,循环遍历markers数组,为每个标注实例绑定click事件,事件处理函数中开启信息窗口并显示是第几个标注。但是通过浏览器看效果的时候却发现问题了:

明明是第三个标注,点击之后的信息窗口中却显示“11”。实际上,当click的监听函数被执行的时候才会去看变量i的值是什么,此时for循环早已经执行完,那么当for循环执行完i的值正好是11。为了达到我们想要的效果,需要增加一层“闭包”:

for (i
=0; i
<10; i
++) {
(function(){
var index
= i;
markers[i].addEventListener('click',
function(){
this.openInfoWindow(new BMap.InfoWindow('我是第'+
(index +1)
+'个标注'));
});
})();
}

上面的代码你可以理解为新增加的函数内部保存了每次循环变量i的值,那么当监听函数执行时将会获取闭包内保存的index变量的值,而不是之前的变量i的值。再看一下,效果OK了:


对地图API事件增强

熟悉google地图API的人可能知道,其事件相关的接口要比百度地图API的接口丰富,除了提供简单的addListener和removeListener之外,还提供了clearListeners、clearInstanceListeners、trigger等方法。那么这些功能在百度地图API中如何实现呢?实际上百度地图API的内部也有事件机制并且与对外公开的事件共用一套机制,如果API提供了诸如clearListeners的方法必然会对API内部的逻辑造成影响,因此也就没有提供类似的接口。如果开发者很喜欢google地图API的事件机制模式并且非用不可怎么办呢,没问题,这里和大家分享一个我的开源项目,名字暂定为EventWrapper,它基于百度地图API,但提供了类似google地图事件机制的接口形式。开源项目地址:https://github.com/jiazheng/EventWrapper。src目录下的main.js就是全部代码了,这是开发版本,如果直接使用可以获取release目录下的eventwrapper.min.js。

我们通过几个例子来看一下它的使用方法,首先需要引用这个js脚本,这里就直接使用github提供的原始数据的地址:

https://raw.github.com/jiazheng/EventWrapper/master/release/eventwrapper.min.js

下面我们添加两个事件监听:

var clickListener
= EventWrapper.addListener(map,
'click',
function(e){
alert(e.point.lng +',
'+ e.point.lat);
});
var dragListener
= EventWrapper.addListener(map,
'dragend',
function(e){
alert(e.point.lng +',
'+ e.point.lat);
});

移除的方式如下:

EventWrapper.removeListener(dragListener);

我们将之前addListener方法返回的对象传递给removeListener即可,这和google的使用方式一致。此外我们还可以清除某个对象所有通过此方式绑定的事件:

EventWrapper.clearInstanceListeners(map);
// 清除map实例所有的事件监听函数

此外EventWrapper还提供了addDomListener、addDomListenerOnce、addListenerOnce、clearListeners和trigger方法,具体使用方法可参考开发版本脚本中的注释信息(开发脚本原始数据地址:https://raw.github.com/jiazheng/EventWrapper/master/src/main.js)。

目前此项目基本完成,但是还没有经过大规模的测试和验证,可能存在不完善的地方,也欢迎广大开发者发现问题并进行反馈。

from:http://www.cnblogs.com/jz1108/archive/2011/07/16/2107199.html

时间: 2024-08-03 17:18:44

百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:的相关文章

百度地图API详解之地图标注

标注(Marker)是用来表示一个点位置的可见元素,每个标注自身都包含地理信息.比如你在西单商场位置添加了一个标注,不论地图移动.缩放,标注都会跟随一起移动,保证其始终指向正确的地理位置. 从上面的图可以看出,不论地图如何变化标注始终指向"西单商场"的位置. 如何知道某个点的坐标? 上例中我们在西单商场位置添加了一个标注,那么我是如何知道它的坐标点呢?可以通过API的事件机制来获取: map.addEventListener('click', function(e){ console.

android-最新版Android百度地图Api中zoomToSpan没有用?求大神解决。。。

问题描述 最新版Android百度地图Api中zoomToSpan没有用?求大神解决... 代码如下: /** * 在百度地图上显示搜索的结果; */ private void showSearchResultInBaiduMap() { MyOverlayManager overlay = new MyOverlayManager(mBaiduMap); mBaiduMap.setOnMarkerClickListener(overlay); overlay.addToMap(); overl

【百度地图API】如何自定义地图图层?实例:制作麻点图(自定义图层+热区)

原文:[百度地图API]如何自定义地图图层?实例:制作麻点图(自定义图层+热区) 摘要:自定义地图图层的用途十分广泛.常见的应用,比如制作魔兽地图和清华校园地图(使用切图工具即可轻松实现).今天我们来学习,当地图上有大量标注,比如600万个的时候,我们如何用"麻点图"来实现标注的展示. -----------------------------------------------------------------------------------------------------

百度地图API-给自定义覆盖物添加事件方法

给marker.lable.circle等Overlay添加事件很简单,直接addEventListener即可.那么,自定义覆盖物的事件应该如何添加呢?我们一起来看一看~ ----------------------------------------------------------------------------------------- 一.定义构造函数并继承Overlay  代码如下 复制代码 // 定义自定义覆盖物的构造函数 function SquareOverlay(cen

百度地图API使用方法详解_php实例

最近做了个项目,其中项目中有个需求需要用到百度地图进行导航,通过查阅相关资料参考百度地图api完成了一个例子. 示例一: API地址:http://developer.baidu.com/map/jsdemo.htm <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> &l

百度地图api如何使用_javascript技巧

如果想用百度地图api,首先需要先获取一个百度地图api的密钥,然后引入百度地图的api,接下来,我们详细介绍下获取.引入api密钥的技巧,以及通过代码给大家详解下百度地图api如何使用,具体请看下文. 首先 ,如果想调用百度地图api,你需要获取一个百度地图api的密钥. 申请密钥很简单,在百度地图api的首页就有相关链接,填写相关信息百度就会给你一个密钥了. 接下来,就是引入百度地图的api 关键代码如下: 复制代码 代码如下: <script type="text/javascrip

Android中使用百度地图API:MyLocationOverlay

本篇文章主要讲解Baidu Map API中MyLocationOverlay的使用.故名思义,MyLocation中文释义为"我的 位置",而Overlay则是"图层"或"覆盖物"的意思,MyLocationOverlay的作用正是用于在地图上标注自己 所处的位置.它跟使用ItemizedOverlay非常相似,只不过MyLocationOverlay标记的只有一个点. 在地图 上标记用户当前所处位置其实是一个GPS定位应用.首先通过GPS定位

基于asp.net的百度地图API编程

问题描述 基于asp.net的百度地图API编程 在地图上的给某个覆盖物添加事件,点击这个覆盖物后出现信息框,信息框的数据从数据库里读出. 解决方案 http://developer.baidu.com/map/jsdemo.htm#d0_2http://developer.baidu.com/map/jsdemo.htm#d0_1http://developer.baidu.com/map/jsdemo.htm#d0_4http://developer.baidu.com/map/jsdemo

急急急!C#web百度地图api调用

问题描述 急急急!C#web百度地图api调用 vs2010下开发的网页地图 实现:从SQL数据库读取全部经纬度信息,然后都标注在地图上 我想实现从数据库读取经纬度,然后把三个点都标注在地图上 已经纠结好长时间了,大家做过的来指导下 解决方案 用DataReader从数据库读取经纬度传串成一个字符串然后赋值给一个全局变量,使用服务器端标签<%%>给aspx页面的js变量,然后js依据这个js变量生成Marker while(dr.Read()) { s+=",{lng:"+