最近一个项目是关于GIS(geographical information system )的,学习了一下GoogleMap,过程中碰到不少问题。
首先:GoogleMap API地址: https://developers.google.com/maps/documentation/javascript/tutorial?hl=zh-CN 去里面看下Demo、API,申请一个Key就可以进行GoogleMap的开发了。
今天看一下第一个问题:多个Market共用一个InfoWindow
先看一下最开始的代码:
1 var points = [{ Longitude: 110.993487, Latitude: 37.997283 }, { Longitude: 112.769617, Latitude: 38.768677 }, { Longitude: 116.913983, Latitude: 26.944184 }, 2 { Longitude: 102.360533, Latitude: 38.130595 }, { Longitude: 114.552137, Latitude: 35.675677 }, { Longitude: 112.320119, Latitude: 37.371388 }, 3 { Longitude: 101.360533, Latitude: 38.130595 }, { Longitude: 104.552137, Latitude: 35.675677 }, { Longitude: 111.320119, Latitude: 37.371388}]; 4 var map; 5 var markers = []; 6 var infowindow = new google.maps.InfoWindow({ 7 maxWidth: 240 8 }); 9 function initialize() { 10 markers = []; 11 var myLatlng0 = new google.maps.LatLng(points[0].Latitude, points[0].Longitude); 12 var mapOptions = { 13 zoom: 4, 14 center: myLatlng0, 15 mapTypeId: google.maps.MapTypeId.ROADMAP 16 } 17 map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions); 18 for (var i = 0; i < points.length; i++) { 19 var myLatlng = new google.maps.LatLng(points[i].Latitude, points[i].Longitude); 20 var marker0 = new google.maps.Marker({ 21 position: myLatlng, 22 map: map, 23 title: i.toString() 24 }); 25 google.maps.event.addListener(marker0, 'click', function () { 26 infowindow.setContent(marker0.getTitle()); 27 infowindow.open(map, marker0); 28 }); 29 } 30 }
运行代码,会发现Market都显示出来了,但是click事件却有个问题,就是不管点哪一个Market,InfoWindow都会显示在最后一个Market上面,且显示的内容都是最后一个Market的。
刚好最近正在看《JavaScript高级程序设计(第2版)》,
好象《JavaScript高级程序设计(第3版)》也出来了。
仔细检查代码,我分析的原因是:JavaScript 变量的作用域是在 function 内,for { } 里面定义的变量在 for { } 以外 function 以内都是可以访问的,包括变量 i 。上面代码 for 循环里定义的变量 marker0 每循环一次只是将变量 marker0 指针的重新指向新创建的对象上,而内存栈里面其实只保存了一个变量 marker0 。
以后写 JavaScript 函数时 第一件事应该就是定义该函数要用到的所有变量。
于是,将代码改成为
1 function initialize() { 2 var marker0; 3 markers = []; 4 var myLatlng0 = new google.maps.LatLng(points[0].Latitude, points[0].Longitude); 5 var mapOptions = { 6 zoom: 4, 7 center: myLatlng0, 8 mapTypeId: google.maps.MapTypeId.ROADMAP 9 } 10 map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions); 11 for (var i = 0; i < points.length; i++) { 12 myLatlng0 = new google.maps.LatLng(points[i].Latitude, points[i].Longitude); 13 marker0 = new google.maps.Marker({ 14 position: myLatlng0, 15 map: map, 16 title: i.toString() 17 }); 18 google.maps.event.addListener(marker0, 'click', function () { 19 showInfoWindow(marker0); 20 }); 21 } 22 } 23 function showInfoWindow(marker0) { 24 infowindow.setContent(marker0.getTitle()); 25 infowindow.open(map, marker0); 26 }
修改后,再运行代码,发现 bug 依旧。继续修改代码为如下就OK了:
1 for (var i = 0; i < points.length; i++) { 2 myLatlng0 = new google.maps.LatLng(points[i].Latitude, points[i].Longitude); 3 marker0 = new google.maps.Marker({ 4 position: myLatlng0, 5 map: map, 6 title: i.toString() 7 }); 8 attachEvent(marker0); 9 } function attachEvent(marker0) { 10 google.maps.event.addListener(marker0, 'click', function () { 11 showInfoWindow(marker0); 12 }); 13 }
最终,我的代码修改成这样的了
1 function initialize1() { 2 markers = []; 3 var myLatlng0 = new google.maps.LatLng(points[0].Latitude, points[0].Longitude); 4 var mapOptions = { 5 zoom: 4, 6 center: myLatlng0, 7 mapTypeId: google.maps.MapTypeId.ROADMAP 8 } 9 map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions); 10 for (var i = 0; i < points.length; i++) { 11 createMarker(i); 12 } 13 } 14 function createMarker(i) { 15 var myLatlng = new google.maps.LatLng(points[i].Latitude, points[i].Longitude); 16 var marker0 = new google.maps.Marker({ 17 position: myLatlng, 18 map: map, 19 title: i.toString() 20 }); 21 google.maps.event.addListener(marker0, 'click', function () { 22 showInfoWindow(marker0); 23 }); 24 }
最后借用书里面的例子说一下 JavaScript 里面参数的传递,先看一下的代码,会弹出什么呢?
1 function setName(localPerson) { 2 localPerson.name = "g_cheng"; 3 localPerson = new Object(); 4 localPerson.name = "the.Cheng"; 5 } 6 var globalPerson = new Object(); 7 setName(globalPerson); 8 alert(globalPerson.name);
JavaScript 里面函数的参数都是按值类型进行传递的。引用类型传递的只是一个指针。程序运行到 setName 时,setName 作用域内变量 localPerson 指向的是全局变量 globalPerson 指向的堆中的一个对象,localPerson globalPerson 指向的是同一个对象,所以执行
localPerson.name = "g_cheng";
会为堆中的对象添加一个 name 的属性,当执行
localPerson = new Object();
localPerson.name = "the.Cheng";
只是把 localPerson 指向了新建的对象上,此时 localPerson globalPerson 分别指向各自的对象。
啰啰嗦嗦写了这么多,感觉也没什么,只是希望对碰到同类问题的 guys 有点帮助。