45 votes

API Google Maps v3 : ajout d'une fenêtre d'information à chaque marqueur

REMARQUE : J'utilise la version 3 de l'API Google Maps.

J'essaie d'ajouter une fenêtre d'information à chaque marqueur que je place sur la carte. Actuellement, je le fais avec le code suivant :

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

Le problème est que lorsque je clique sur un marqueur, la fenêtre d'information du dernier marqueur ajouté s'affiche. Par ailleurs, pour être clair, la fenêtre d'information apparaît à côté du dernier marqueur et non du marqueur sur lequel j'ai cliqué. J'imagine que mon problème se situe dans la partie addListener, mais je ne suis pas certain. Avez-vous une idée ?

79voto

Daniel Vassallo Points 142049

Vous avez un problème de fermeture très courant dans le for in boucle :

Les variables enfermées dans une fermeture partagent le même environnement unique, de sorte qu'au moment où la variable click de l'appel de la addListener est appelé, la boucle aura suivi son cours et l'option info sera laissée pointant vers le dernier objet, qui se trouve être le dernier InfoWindow créé.

Dans ce cas, une manière simple de résoudre ce problème serait d'augmenter votre Marker avec l'objet InfoWindow :

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

Ce sujet peut être assez délicat si vous n'êtes pas familier avec le fonctionnement des fermetures. Vous pouvez consulter l'article suivant de Mozilla pour une brève introduction :

Gardez aussi à l'esprit que l'API v3 permet de multiples InfoWindow sur la carte. Si vous avez l'intention de n'avoir qu'un seul InfoWindow visible à ce moment-là, vous devez plutôt utiliser une seule InfoWindow puis de l'ouvrir et de modifier son contenu chaque fois que le marqueur est cliqué ( Fuente ).

35voto

ostapische Points 516

Vous pouvez utiliser this dans l'événement :

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

9voto

ceasaro Points 261

L'application add_marker présente toujours un problème de fermeture, car elle utilise la variable marker en dehors de la portée de google.maps.event.addListener.

Une meilleure mise en œuvre serait :

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

J'ai également utilisé la carte du marqueur, de cette façon vous n'avez pas besoin de passer l'objet google map, vous voulez probablement utiliser la carte à laquelle le marqueur appartient de toute façon.

1voto

blcArmadillo Points 1872

Salut tout le monde. Je ne sais pas si c'est la meilleure solution, mais je me suis dit que j'allais la poster ici pour espérer aider les gens à l'avenir. Veuillez commenter si vous voyez quelque chose qui devrait être changé.

Mes boucles de for sont maintenant :

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

Et add_marker est défini comme suit :

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

Vous pouvez utiliser info_window.close() pour désactiver la fenêtre d'information à tout moment. J'espère que cela aidera quelqu'un.

1voto

Al-Chalabee Points 11

Pour les API des plugins Earth, créez le ballon en dehors de votre boucle et passez votre compteur à la fonction pour obtenir un contenu unique pour chaque marqueur !

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X