web-dev-qa-db-fra.com

API Google Maps v3 ajoutant un InfoWindow à chaque marqueur

REMARQUE: j'utilise la v3 de l'API Google Maps.

J'essaie d'ajouter une fenêtre d'informations à chaque marqueur que j'ai mis 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, il affiche simplement la fenêtre d’informations du dernier marqueur ajouté. De plus, pour que tout soit clair, la fenêtre d’information apparaît à côté du dernier marqueur et non du marqueur sur lequel vous avez cliqué. J'imagine que mon problème se situe dans la partie addListener mais que je ne suis pas postitif. Des idées?

44
blcArmadillo

Vous rencontrez un problème de fermeture très courant dans la boucle for in:

Les variables incluses dans une fermeture partagent le même environnement unique. Ainsi, au moment où le rappel click de la addListener est appelé, la boucle aura suivi son cours et la variable info sera laissée pointée vers le dernier InfoWindow créé.

Dans ce cas, un moyen simple de résoudre ce problème consiste à augmenter votre objet Marker avec la variable 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);
});

Cela peut être un sujet assez délicat si vous ne connaissez pas le fonctionnement des fermetures. Vous pouvez consulter l’article suivant sur Mozilla pour une brève introduction:

N'oubliez pas non plus que l'API v3 autorise plusieurs InfoWindows sur la carte. Si vous avez l'intention de n'avoir qu'une seule variable InfoWindow visible à la fois, vous devez plutôt utiliser un seul objet InfoWindow, puis l'ouvrir et modifier son contenu à chaque clic sur le marqueur ( Source ).

79
Daniel Vassallo

Vous pouvez utiliser this dans les cas suivants: 

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

L'add_marker a toujours un problème de fermeture, car il utilise la variable de marqueur 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 aussi 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.

9
ceasaro

Salut tout le monde. Je ne sais pas si c'est la solution optimale, mais j'ai décidé de la poster ici pour aider, espérons-le, les gens dans le futur. Veuillez commenter si vous voyez quelque chose qui devrait être changé.

Ma boucle est 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:

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 info_window à tout moment. J'espère que ça aide quelqu'un.

1
blcArmadillo

pour les API de plug-in Earth, créez la bulle en dehors de votre boucle et transmettez votre compteur à la fonction pour obtenir un contenu unique pour chaque repère!

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);
            });
        }
1
Al-Chalabee

Dans mon cas (Utilisation de Javascript dans Razor) Cela fonctionnait parfaitement dans une boucle Foreach. 

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

J'avais un problème similaire. Si tout ce que vous voulez, c’est que certaines informations soient affichées lorsque vous survolez un marqueur au lieu de cliquer dessus, j’ai trouvé qu’une bonne alternative à l’utilisation d’une fenêtre d’informations était de définir un titre sur le marqueur. Ainsi, chaque fois que vous passez la souris sur le marqueur, le titre s’affiche comme une balise ALT. 'marker.setTitle (' Marker '+ id);' Il n'est plus nécessaire de créer un écouteur pour le marqueur.

0
cormacio100

La seule façon pour que cela fonctionne enfin est de créer un tableau en JavaScript. Les éléments du tableau font référence aux différentes fenêtres d’information (une fenêtre d’information est créée pour chaque marqueur de la carte). Chaque élément de tableau contient le texte unique correspondant à son marqueur de carte approprié. J'ai défini l'événement JavaScript pour chaque fenêtre d'information en fonction de l'élément de tableau. Et lorsque l'événement se déclenche, j'utilise le mot clé "this" pour référencer l'élément de tableau afin de référencer la valeur appropriée à afficher.

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

Essaye ça:

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
JochenJung