2011-08-12 9 views
33

Actualmente estoy usando el siguiente código para colocar varios marcadores en un mapa de Google usando su API.Agregar múltiples marcadores con infowindows (Google Maps API)

El problema que estoy teniendo es que varias ventanas de información no funcionan (solo muestra la última).

Hay un montón de preguntas como la mía aquí en SO. En realidad hacen que un chingo de preguntas :-)

Sólo un ejemplo: Trying to bind multiple InfoWindows to multiple Markers on a Google Map and failing

La solución a mi problema es un poco fácil: basta con encerrar el detector de clics a una función (anónimo).

Sin embargo, lo que no entiendo es por qué mi solución no está funcionando (guardando los marcadores e infowindows en matrices en lugar de solo una variable).

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

Así que ... no lo que para obtener la solución de cómo conseguir que funcione con alguna función para encerrar al oyente (aunque debe trabajar, no han probado todavía, pero lo hará), pero Quiero saber el motivo por el que no funcionaría si agrego los marcadores y las ventanas de información a las matrices.

Respuesta

62

Javascript tiene una estructura de lenguaje llamada "cierres". Los cierres son funciones (como la función() {} que declaras arriba para tratar con el oyente click) que capturan referencias a variables externas.

Hay un montón de recursos que les explique mejor que yo, lo que le sugiero que consulte, pero aquí está mi mejor intento:

En este bloque aquí:

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

Porque "clave" es ya definida como una variable externa, la función capturará una referencia a esa variable. Entonces, ¿dónde esperas:

infowindows["helloworld"] 

Javascript en su lugar interpretar esto como:

infowindows[reference to key] 

Al hacer clic en un marcador, que mira hacia arriba "referencia a la clave" para ver cuál es el valor actual de la clave es . Debido a que esto probablemente no ocurra hasta que su ciclo haya finalizado, la clave será igual a la última clave en su objeto data.markers. Y será igual a ese valor para CADA clic en el oyente que haya agregado.

La solución, como usted señala, es ajustar esto en una función anónima para obtener Javascript y evaluar el valor de "clave" en el momento en que se agrega el detector de clics.

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

Hay una manera un poco más simple de lograr esto. puede agregar un atributo personalizado a su marcador (el índice de la ventana de información) y referirse a él en la función de devolución de llamada. Ejemplo a continuación:

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); 
    } 
+0

estoy tratando de esta manera, pero tengo una advertencia jshint "No haga las funciones dentro de un bucle". Si tomo al oyente fuera de loop obtengo el error "marker used out of scope". ¿Cómo puedo evitarlo? – aitor

8

This uno es bastante buena explicación con una solución con la página de demostración.

This es la página de demostración.

+0

Lo sentimos, ambas demostraciones no están disponibles. – aaa

54

¡Esto funciona bien para mí!Simplemente agregue una nueva propiedad al objeto marcador, esta propiedad contiene el objeto 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); 

}); 
+4

¡Esto no responde la pregunta original en absoluto! Simplemente muestra el ejemplo de la referencia de la API de Google Maps con UNA ventana de información. Lo siento, pero esta respuesta no debería estar aquí. – Zordid

+0

manera más limpia y esto respondió lo que estaba buscando. ¡Gracias! –

1

voy a utilizar de cierre:

(function(infowindow, marker){google.maps.event.addListener(marker, 'click', function() { 
    infowindow.open(map, marker); 
});})(infowindow, marker) 
2
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); 
0
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); 
}); 
} 
+1

¡Bienvenido a Stack Overflow! Si bien este código puede responder a la pregunta, proporcionar un contexto adicional con respecto a por qué y/o cómo responde este código a la pregunta mejora su valor a largo plazo. – Ajean

Cuestiones relacionadas