百度地图的覆盖物有很多种,比如点、折线等等。项目要求在地图上划出多个折线,并需要对这些折线绑定事件处理函数(弹出一个信息窗口)。
折线与信息窗口的定义代码如下:
var DeniroMap = {
lines: [],//存储已创建好的折线对象数组
//折线样式
lineStyle: {strokeColor: "blue", strokeWeight: 6, strokeOpacity: 0.5},
/**
* 新增折线
* @param map
* @param coordinate 坐标
*/
addLine: function (map, coordinate) {
var line = new BMap.Polyline([
new BMap.Point(coordinate.x1, coordinate.x2),
new BMap.Point(coordinate.y1, coordinate.y2)
]);
map.addOverlay(line, this.lineStyle);
this.lines.push(line);
},
//信息窗口配置
infoWindowCfg: {
width: 200,//宽度
height: 100,//高度
title: "deniro"//标题
}
};
接下来创建了两个折线:
//创建两个折线
DeniroMap.addLine(map, {
x1: 116.399,
x2: 39.910,
y1: 116.405,
y2: 39.920
});
DeniroMap.addLine(map, {
x1: 116.300,
x2: 39.900,
y1: 116.400,
y2: 39.900
});
这里特意画了两个离得比较近的折线,这样方便调试:
现在开始为多条折线绑定事件吧:
//开始绑定
var i, line, index, length = DeniroMap.lines.length;
var indexArray = [1, 2];//假定要传递给每个覆盖物的参数
//错误的绑定
for (i = 0; i < length; i++) {
line = DeniroMap.lines[i];
index = indexArray[i];
line.addEventListener("click", function(event){
var infoWindow = new BMap.InfoWindow(index + "", DeniroMap.infoWindowCfg);
map.openInfoWindow(infoWindow, event.point);
});
}
运行时发现,点击每一个折线,居然都是返回 2!我们希望的是第一条折线返回的是 1,第二条折线返回的是 2。到底哪里出了问题?
原来是闭包惹的祸!这些折线的 click 事件函数,它们的作用域链中引用的都是同一个变量 index。所以我们不管点击哪一条折线,最后看到的都是 2。
解决办法是:在内部创建另一个匿名函数让闭包行为符合我们的预期:
//正确的绑定
for (i = 0; i < length; i++) {
line = DeniroMap.lines[i];
index = indexArray[i];
var clickFunction = function (i) {
return function (event) {
var infoWindow = new BMap.InfoWindow(i + "", DeniroMap.infoWindowCfg);
map.openInfoWindow(infoWindow, event.point);
};
}(index);
line.addEventListener("click", clickFunction);
}
在调用每一个匿名函数时,我们传入了变量 index。因为函数的参数是按值传递的,所以会将变量 index 的当前值复制给内部的 i。在这个匿名函数内部,我们创建并返回了 click 函数,这个函数在内部访问了 i 的闭包。因为 openInfoWindow 方法需要 event 对象,所以我们把 event 作为 click 函数的参数传入了这个最内部的匿名函数咯。
问题解决啦,是不是很开心呀O(∩_∩)O~