2010-07-01 9 views
44

Hinweis hinzufügen: Ich bin mit v3 der Google Maps APIGoogle Maps v3 API ein Infofenster zu jeder Markierung

Ich versuche, ein Info-Fenster zu jeder Markierung hinzufügen ich auf die Karte setzen. Zur Zeit mache ich dies mit dem folgenden Code:

for (var i in tracks[racer_id].data.points) { 
    values = tracks[racer_id].data.points[i];     
    point = new google.maps.LatLng(values.lat, values.lng); 
    if (values.qst) { 
     var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
     tracks[racer_id].markers[i] = marker; 
     var info = new google.maps.InfoWindow({ 
      content: '<b>Speed:</b> ' + values.inst + ' knots' 
     }); 
     tracks[racer_id].info[i] = info; 
     google.maps.event.addListener(marker, 'click', function() { 
      info.open(map, marker); 
     }); 
    } 
    track_coordinates.push(point); 
    bd.extend(point); 
} 

Das Problem ist, wenn ich auf einer Markierung klicken zeigt es nur auf die Info-Fenster für die letzte Markierung hinzugefügt. Außerdem wird das Info-Fenster neben dem letzten Marker und nicht mit dem angeklickten Marker angezeigt. Ich könnte mir vorstellen, dass mein Problem im AddListener-Teil liegt, aber nicht postive. Irgendwelche Ideen?

Antwort

78

Sie haben a very common closure problem in der for in Schleife:

Variablen in einem Verschluss die gleiche einzigen Umgebung eingeschlossen ist, so durch die Zeit, die click Rückruf vom addListener aufgerufen wird, haben die Schleife seinen Lauf und die laufen info Variable wird links auf das letzte Objekt, das die letzte InfoWindow erstellt wird links verlassen werden.

In diesem Fall ist eine einfache Möglichkeit, dieses Problem zu lösen wäre Ihr Marker Objekt mit den InfoWindow zu erweitern:

var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 

marker.info = new google.maps.InfoWindow({ 
    content: '<b>Speed:</b> ' + values.inst + ' knots' 
}); 

google.maps.event.addListener(marker, 'click', function() { 
    marker.info.open(map, marker); 
}); 

Das ist ganz ein heikles Thema sein kann, wenn Sie nicht vertraut sind mit, wie Verschlüssen Arbeit . Sie können den folgenden Mozilla-Artikel für eine kurze Einführung überprüfen:

Denken Sie auch daran, dass die v3 API mehr InfoWindow s auf der Karte ermöglicht. Wenn Sie zu diesem Zeitpunkt nur eine InfoWindow haben möchten, sollten Sie stattdessen ein einziges InfoWindow-Objekt verwenden und dieses dann öffnen und den Inhalt ändern, wenn auf die Markierung geklickt wird (Source).

+1

Können Sie mehr darüber erklären, wo ich dieses Code-Snippet einstecken muss? Ist es statt for Schleife oder vor for-Schleife bin ich etwas verwirrt. – uday

+1

Sie müssen das Code-Snippet _inside_ die for-Schleife einfügen;) – Tilt

0

Try this:

for (var i in tracks[racer_id].data.points) { 
    values = tracks[racer_id].data.points[i];     
    point = new google.maps.LatLng(values.lat, values.lng); 
    if (values.qst) { 
     var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
     tracks[racer_id].markers[i] = marker; 
     var info = new google.maps.InfoWindow({ 
      content: '<b>Speed:</b> ' + values.inst + ' knots' 
     }); 
     tracks[racer_id].info[i] = info; 
     google.maps.event.addListener(tracks[racer_id].markers[i], 'click', function() { 
      tracks[racer_id].info[i].open(map, tracks[racer_id].markers[i]); 
     }); 
    } 
    track_coordinates.push(point); 
    bd.extend(point); 
} 
+0

Haha versucht hatte ich schon. Habe es nochmal probiert und leider klappt es immer noch nicht. – blcArmadillo

+0

Das Problem ist hier die Variable "i", die immer noch in einem Verschluss eingeschlossen ist. Wenn der "Klick" -Rückruf aufgerufen wird, wird die "i" -Variable auf das letzte Element der Schleife zeigen und daher wird "info [i] .open" immer noch das letzte "InfoWindow" öffnen. –

0

ich ein sehr ähnliches Problem hatte, aber in Actionscript 3: Stack Over Flow: Dynamic Google Maps API Info Window HTML Content Issue

Ich habe versucht, aus einer Datenbank eindeutige Informationen in die htmlcontent des Tooltips zu ziehen und festgestellt, dass Ich erhielt die Information des letzten Markers, den ich in jedem Marker hinzugefügt habe.

Angenommen, es handelt sich nicht um ein ActionScript-spezifisches Problem, dann funktioniert die Lösung von JochenJung nicht. Sehen Sie sich die Lösung an, die ich in meinem Problem veröffentlicht habe, und sehen Sie, ob Sie sie hier anwenden können. Dies scheint ein ernstes Problem mit der Map-API zu sein.

1

Hey alle. Ich weiß nicht, ob das die optimale Lösung ist, aber ich dachte, ich würde es hier posten, um hoffentlich den Leuten in der Zukunft zu helfen. Bitte kommentieren Sie, wenn Sie etwas sehen, das geändert werden sollte.

Meine for-Schleifen ist jetzt:

for (var i in tracks[racer_id].data.points) { 
    values = tracks[racer_id].data.points[i];     
    point = new google.maps.LatLng(values.lat, values.lng); 
    if (values.qst) { 
     tracks[racer_id].markers[i] = add_marker(racer_id, point, '<b>Speed:</b> ' + values.inst + ' knots<br /><b>Invalid:</b> <input type="button" value="Yes" /> <input type="button" value="No" />'); 
    } 
    track_coordinates.push(point); 
    bd.extend(point); 
} 

Und add_marker ist definiert als:

var info_window = new google.maps.InfoWindow({content: ''}); 

function add_marker(racer_id, point, note) { 
    var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
    marker.note = note; 
    google.maps.event.addListener(marker, 'click', function() { 
     info_window.content = marker.note; 
     info_window.open(map, marker); 
    }); 
    return marker; 
} 

Sie info_window.close verwenden können(), um die info_window jederzeit auszuschalten. Hoffe, das hilft jemandem.

9

Der add_marker hat immer noch ein Schließproblem, da er die Marker-Variable außerhalb des Bereichs google.maps.event.addListener verwendet.

Eine bessere Implementierung wäre:

function add_marker(racer_id, point, note) { 
    var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
    marker.note = note; 
    google.maps.event.addListener(marker, 'click', function() { 
     info_window.content = this.note; 
     info_window.open(this.getMap(), this); 
    }); 
    return marker; 
} 

ich die Karte auch von der Markierung verwendet wird, auf diese Weise Sie nicht über die Google-Map-Objekt übergeben müssen, können Sie die Karte, wo die Markierung wahrscheinlich verwenden möchten gehört sowieso dazu.

+0

Wow! Ich war mehr als zwei Stunden dabei! wusste nicht, dass der Marker außerhalb des Scope verwendet würde! Danke vielmals! –

1

für Earth-Plugin-APIs, erstellen Sie die Sprechblase außerhalb Ihrer Schleife und übergeben Sie Ihren Zähler an die Funktion, um eindeutige Inhalte für jede Ortsmarke zu erhalten!

function createBalloon(placemark, i, event) { 
      var p = placemark; 
      var j = i; 
      google.earth.addEventListener(p, 'click', function (event) { 
        // prevent the default balloon from popping up 
        event.preventDefault(); 
        var balloon = ge.createHtmlStringBalloon(''); 
        balloon.setFeature(event.getTarget()); 

        balloon.setContentString('iframePath#' + j); 

        ge.setBalloon(balloon); 
      }); 
     } 
33

Sie können this in Fall verwenden:

google.maps.event.addListener(marker, 'click', function() { 
    // this = marker 
    var marker_map = this.getMap(); 
    this.info.open(marker_map); 
    // this.info.open(marker_map, this); 
    // Note: If you call open() without passing a marker, the InfoWindow will use the position specified upon construction through the InfoWindowOptions object literal. 
}); 
+10

Dies sollte die richtige Antwort sein. Die Antwort @DanielVassallo leidet unter dem gleichen Problem, auf das er Bezug genommen hat. –

+0

Das hat auch für mich funktioniert ... das war der Schlüssel. –

+3

Funktioniert gut, aber ich musste 'this.info.open (marker_map, this); ' – askilondz

0

Der einzige Weg, ich schließlich das ein Array in JavaScript, indem war zur Arbeit bekommen konnte. Die Array-Elemente verweisen auf die verschiedenen Info-Fenster (für jeden Marker auf der Karte wird ein Info-Fenster erstellt). Jedes Array-Element enthält den eindeutigen Text für die entsprechende Kartenmarkierung. Ich habe das JavaScript-Ereignis für jedes Info-Fenster basierend auf dem Array-Element definiert. Und wenn das Ereignis ausgelöst wird, verwende ich das Schlüsselwort "this", um auf das Array-Element zu verweisen, um auf den entsprechenden anzuzeigenden Wert zu verweisen.

var map = new google.maps.Map(document.getElementById('map-div'), mapOptions); 
zipcircle = []; 
for (var zip in zipmap) { 
    var circleoptions = { 
     strokeOpacity: 0.8, 
     strokeWeight: 1, 
     fillOpacity: 0.35, 
     map: map, 
     center: zipmap[zip].center, 
     radius: 100 
    }; 
    zipcircle[zipmap[zip].zipkey] = new google.maps.Circle(circleoptions); 
    zipcircle[zipmap[zip].zipkey].infowindowtext = zipmap[zip].popuptext; 
    zipcircle[zipmap[zip].zipkey].infowindow = new google.maps.InfoWindow(); 
    google.maps.event.addListener(zipcircle[zipmap[zip].zipkey], 'click', function() { 
     this.infowindow.setContent(this.infowindowtext); 
     this.infowindow.open(map, this); 
    }); 
} 
4

Verwenden Ereignis Verschlüsse ...

Dies ist, wie es in v3 zu tun: https://developers.google.com/maps/documentation/javascript/examples/event-closure

+1

Es ist besser, ein Beispiel einzuschließen und stattdessen eine Weiterleitung an einen Link vorzunehmen. Wenn dieser Link nicht mehr angezeigt wird, hilft Ihr Beispiel weiter und Sie beantworten eine sehr alte Frage (4 Jahre alt). –

+1

Die Methode in diesem Beispiel funktioniert für mich. Erstellen Sie "Info" in Ihrer Schleife, aber erstellen Sie dann eine separate Funktion, die den "Marker" und die "Info" verwendet, um das InfoWindow und den Listener für das Ereignis zu erstellen. @ ostatische Antwort hat die richtigen Ereignisfenster erstellt, aber sie waren alle an Orten, die nicht mit einem bestimmten Marker verbunden waren. –

+0

Dies ist eine gute Ressource. ES2015 lass Block Scoping wahrscheinlich kümmert sich das jetzt. – sheriffderek

0

hatte ich ein ähnliches Problem. Wenn Sie nur möchten, dass einige Informationen angezeigt werden, wenn Sie den Mauszeiger über einen Marker bewegen, anstatt ihn anzuklicken, habe ich festgestellt, dass eine gute Alternative zum Verwenden eines Info-Fensters darin besteht, einen Titel auf dem Marker festzulegen. Wenn Sie die Maus über den Marker bewegen, wird der Titel wie ein ALT-Tag angezeigt. 'marker.setTitle (' Markierung '+ id);' Es beseitigt die Notwendigkeit, einen Hörer für den Marker

1

zu erstellen In meinem Fall (mit Javascript insidde Razor) Das funktionierte perfekt in einer Foreach-Schleife

google.maps.event.addListener(marker, 'click', function() { 
    marker.info.open(map, this); 
}); 
Verwandte Themen