Aggiunta di più marcatori con infowindows (API di Google Maps)

Attualmente sto usando il seguente codice per posizionare più indicatori su una mappa di Google utilizzando la loro API.

Il problema che sto avendo è con più infowindows non funziona (mostrando solo l’ultimo).

Ci sono un sacco di domande come la mia qui su SO. Effettivamente fai un sacco di domande 🙂

Solo un esempio: cercando di associare più windows di informazioni a più marcatori su una mappa di Google e in mancanza

La soluzione al mio problema è piuttosto semplice: basta accludere l’ascoltatore dei clic a una funzione (anonima).

Tuttavia, ciò che non capisco è il motivo per cui la mia soluzione non funziona (salvando i marcatori e le infowindows negli array invece di una sola variabile).

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]); }); } } 

Quindi … non so come ottenere la soluzione come farlo funzionare con alcune funzioni per racchiudere l’ascoltatore (anche se dovrebbe funzionare, non l’ho ancora testato ma lo farà), ma voglio sapere il motivo per cui non funzionerebbe se aggiungessi i marcatori e le infowindows agli array.

Javascript ha una struttura linguistica chiamata “chiusure”. Le chiusure sono funzioni (come la funzione () {} che dichiari in precedenza di trattare con l’ascoltatore di clic) che acquisisce riferimenti a variabili esterne.

Ci sono molte risorse che le spiegano meglio di me, che consiglio di consultare, ma ecco il mio tentativo migliore:

In questo blocco qui:

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

Poiché “chiave” è già definita come variabile esterna, la funzione acquisirà un riferimento a tale variabile. Quindi, dove ti aspetti:

 infowindows["helloworld"] 

Javascript interpreterà questo come:

 infowindows[reference to key] 

Quando fai clic su un marker, cerca “reference to key” per vedere qual è il valore corrente della chiave. Perché questo probabilmente non succederà fino a quando il ciclo non sarà terminato, la chiave sarà uguale a qualunque sia l’ultima chiave nell’object data.markers. E sarà uguale a quel valore per OGNI lettore di clic che hai aggiunto.

La soluzione, come lei sottolinea, è di avvolgere questo in una funzione anonima per ottenere Javascript per valutare il valore di “chiave” nel momento in cui viene aggiunto il listener di clic.

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

Questo funziona bene per me! Basta aggiungere una nuova proprietà all’object marcatore, questa proprietà contiene l’object 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); }); 

C’è un modo leggermente più semplice per realizzare questo. puoi aggiungere un attributo personalizzato al tuo indicatore (l’indice della finestra delle informazioni) e fare riferimento ad esso nella funzione di callback. Esempio di seguito:

  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 = "

" + earthquakes[i].title + "

" + "Link to shakemap."; 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); }

Questa è una spiegazione abbastanza buona con la soluzione con la pagina demo.

Questa è la pagina demo.

  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 = "

Hello World

"; 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);

userò la chiusura:

 (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: '
'+data.dbreturn[i].nome+'
' }); google.maps.event.addListener(marker, "click", function () { infowindow.setContent(this.html); infowindow.open(map, this); }); }