使用infowindows(Google Maps API)添加多个标记

我目前使用下面的代码在Google Map上使用他们的API来放置多个标记。

我遇到的问题是多个infowindows不工作(只显示最后一个)。

SO上有很多像我这样的问题。 其实使这个问题的一大堆:-)

只是一个例子: 尝试将多个InfoWindows绑定到Google Map上的多个标记并失败

我的问题的解决scheme是相当容易的:只需将点击侦听器附加到(匿名)函数。

然而,我不明白的是为什么我的解决scheme不工作(保存数组中的标记和infowindows而不是一个variables)。

var markers = []; var infowindows = []; // add shops or malls for (var key in data.markers) { if (data.markers.hasOwnProperty(key)) { infowindows[key] = new google.maps.InfoWindow({ content: data.markers[key].infowindow }); markers[key] = new google.maps.Marker({ position: new google.maps.LatLng(data.markers[key].location.lat, data.markers[key].location.lng), map: map, flat: true, title: data.markers[key].name, draggable: false }); var iconFile = 'http://maps.google.com/mapfiles/ms/icons/'+marker_color+'-dot.png'; markers[key].setIcon(iconFile); google.maps.event.addListener(markers[key], 'click', function() { infowindows[key].open(map, markers[key]); }); } } 

所以…我不知道如何得到它的解决scheme如何使用一些函数来封闭监听器(虽然它应该工作,还没有testing过,但会),但我想知道为什么它如果我将标记和infowindows添加到数组,则不起作用。

Javascript有一个叫做“closures”的语言结构。 闭包是函数(如上面声明的函数(){}来处理单击监听器),它捕获对外部variables的引用。

有很多资源可以比我更好地解释它们,我build议你参考一下,但这是我最好的尝试:

在这个块里:

  google.maps.event.addListener(markers[key], 'click', function() { infowindows[key].open(map, markers[key]); }); 

因为“key”已经被定义为一个外部variables,所以该函数将捕获对该variables的引用。 所以你期望的地方:

 infowindows["helloworld"] 

JavaScript会改为将其解释为:

 infowindows[reference to key] 

当你点击一个标记时,它会查找“引用键”,看看键的当前值是什么。 因为这可能不会发生,直到你的循环完成,关键将等于你的data.markers对象是最后一个键。 它将等于您添加的每个点击监听器的值。

正如您所指出的,解决scheme是将其包含在一个匿名函数中,以便在添加单击侦听器时使用Javascript来评估“key”的值。

  google.maps.event.addListener(markers[key], 'click', function(innerKey) { return function() { infowindows[innerKey].open(map, markers[innerKey]); } }(key)); 

这对我来说很好! 只需将一个新的属性添加到标记对象,该属性包含infowindow对象。

 var mytext = 'Infowindow contents in HTML' var myinfowindow = new google.maps.InfoWindow({ content: mytext }); var marker = new google.maps.Marker({ position: mypos, map: mymap, icon: myicon, title: mytitle, infowindow: myinfowindow }); google.maps.event.addListener(marker, 'click', function() { this.infowindow.open(map, this); }); 

有一个简单的方法来完成这个。 您可以将自定义属性添加到标记(信息窗口的索引),并在callback函数中引用它。 示例如下:

  markers = Array(); infoWindows = Array(); for(var i in earthquakes) { var location = new google.maps.LatLng(earthquakes[i].geolat, earthquakes[i].geolong); var marker = new google.maps.Marker({ position : location, map : map, animation : google.maps.Animation.DROP, infoWindowIndex : i //<---Thats the extra attribute }); var content = "<h3>" + earthquakes[i].title + "<h3>" + "<a data-ajax='false' target='_blank' href='" + earthquakes[i].link + "'>Link to shakemap.</a>"; var infoWindow = new google.maps.InfoWindow({ content : content }); google.maps.event.addListener(marker, 'click', function(event) { map.panTo(event.latLng); map.setZoom(5); infoWindows[this.infoWindowIndex].open(map, this); } ); infoWindows.push(infoWindow); markers.push(marker); } 

这个与演示页面的解决scheme是很好的解释。

这是演示页面。

  function addMarker(Latlng){ marker = new google.maps.Marker({ position: Latlng, icon:"myicon.jpg", map: map, animation: google.maps.Animation.DROP, title:"My tooltip" }); //add marker marker.setMap(map); contentString = "<h1>Hello World</h1>"; marker.infowindow = new google.maps.InfoWindow({ content: contentString }); //add click event google.maps.event.addListener(marker, 'click', function(){ this.infowindow.open(map,this); }); } addMarker(some_lat_lang_value); 

我将使用闭包:

 (function(infowindow, marker){google.maps.event.addListener(marker, 'click', function() { infowindow.open(map, marker); });})(infowindow, marker) 
 var infowindow = null; infowindow = new google.maps.InfoWindow({ content: "loading..." }); for (i = 0; i < data.dbreturn.length; i++) { var latilongi = data.dbreturn[i].mapa.split(','); var mapinha = {lat: parseFloat(latilongi['0']), lng: parseFloat(latilongi['1'])}; var marker = new google.maps.Marker({ position: mapinha, html: '<div id="content"><h5 id="firstHeading" class="firstHeading">'+data.dbreturn[i].nome+'</h5></div>' }); google.maps.event.addListener(marker, "click", function () { infowindow.setContent(this.html); infowindow.open(map, this); }); }