Ouvrez une seule InfoWindow dans l'API Google Maps v3

85

Je n'ai besoin que d'une seule InfoWindow ouverte sur ma carte Google. Je dois fermer toutes les autres InfoWindows avant d'en ouvrir une nouvelle.

Quelqu'un peut-il me montrer comment faire cela?

Leo
la source
Qu'as-tu essayé?
IgniteCoders

Réponses:

151

Vous devez créer un seul InfoWindowobjet, en garder une référence et le réutiliser pour tous les marqueurs. Citant les documents de l'API Google Maps :

Si vous ne souhaitez afficher qu'une seule fenêtre d'informations à la fois (comme c'est le cas sur Google Maps), vous n'avez besoin de créer qu'une seule fenêtre d'informations, que vous pouvez réaffecter à différents emplacements ou marqueurs lors d'événements cartographiques (tels que les clics d'utilisateurs).

Par conséquent, vous souhaiterez peut-être simplement créer l' InfoWindowobjet juste après avoir initialisé votre carte, puis gérer les clickgestionnaires d'événements de vos marqueurs comme suit. Disons que vous avez un marqueur appelé someMarker:

google.maps.event.addListener(someMarker, 'click', function() {
   infowindow.setContent('Hello World');
   infowindow.open(map, this);
});

Ensuite, le InfoWindowdevrait se fermer automatiquement lorsque vous cliquez sur un nouveau marqueur sans avoir à appeler la close()méthode.

Daniel Vassallo
la source
Je fais cela aussi mais est-il normal que infoWindow prenne environ +1 seconde pour s'ouvrir sur le marqueur suivant? parfois il ne s'ouvre pas du tout. J'utilise exactement le même code
MJB
Daniel, super idée !! avant cela, j'essayais de synchroniser manuellement, mais cela montre des erreurs javascript étranges (comme "c is null" dans main.js, ou quelque chose comme (123 hors de portée 43)).
Victor
30

Créez votre infowindow hors de la portée afin de pouvoir la partager.

Voici un exemple simple:

var markers = [AnArrayOfMarkers];
var infowindow = new google.maps.InfoWindow();

for (var i = 0, marker; marker = markers[i]; i++) {
  google.maps.event.addListener(marker, 'click', function(e) {
    infowindow.setContent('Marker position: ' + this.getPosition());
    infowindow.open(map, this);
  });
}
skarE
la source
Merci. Utiliser "this" a résolu la plupart de mes problèmes. Je ne comprends toujours pas comment utiliser du contenu personnalisé dans setContent. Par exemple, dans ma boucle de marqueurs, je crée une variable contentHtml en utilisant la variable "i" et en la liant à un objet de base de données. Comment puis-je transmettre cette variable contentHtml à l'auditeur?
Ryan
Dans mon cas, la fenêtre ne s'ouvre que lorsque j'utilise "this" dans infowindow.open (map, this); Au lieu de "marqueur". Merci de partager votre solution.
posséder
Je fais cela aussi mais est-il normal que infoWindow prenne environ +1 seconde pour s'ouvrir sur le marqueur suivant? parfois il ne s'ouvre pas du tout. J'utilise exactement le même code
MJB
14

J'ai eu le même problème mais la meilleure réponse ne l'a pas complètement résolu, ce que j'avais à faire dans ma déclaration for était d'utiliser le this relatif à mon marqueur actuel. Peut-être que cela aide quelqu'un.

for(var i = 0; i < markers.length; i++){
    name = markers[i].getAttribute("name");
    address = markers[i].getAttribute("address");        
    point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));                                     
    contentString = '<div style="font-family: Lucida Grande, Arial, sans-serif;>'+'<div><b>'+ name +'</b></div>'+'<div>'+ address +'</div>';                    
    marker = new google.maps.Marker({                       
        map: map,
        position: point,
        title: name+" "+address,
        buborek: contentString 
    });                                     
    google.maps.event.addListener(marker, 'click', function(){
        infowindow.setContent(this.buborek); 
        infowindow.open(map,this); 
    });                                                         
    marker.setMap(map);                 
}
Ferenc Takacs
la source
2
La façon dont vous passez le contentString m'a été utile, merci.
posséder
4

un peu tard, mais j'ai réussi à n'avoir qu'une seule infowindow ouverte par maken infowindow une variable globale.

var infowindow = new google.maps.InfoWindow({});

puis à l'intérieur du listner

infowindow.close();
infowindow = new google.maps.InfoWindow({   
    content: '<h1>'+arrondissement+'</h1>'+ gemeentesFiltered                           
});

infowindow.open(map, this);
user2827958
la source
1
Fonctionne très bien pour moi :)
lumos
4

Déclarez un globar var selectedInfoWindow;et utilisez-le pour contenir la fenêtre d'informations ouverte:

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

// Open the infowindow on marker click
google.maps.event.addListener(marker, "click", function() {
    //Check if there some info window selected and if is opened then close it
    if (selectedInfoWindow != null && selectedInfoWindow.getMap() != null) {
        selectedInfoWindow.close();
        //If the clicked window is the selected window, deselect it and return
        if (selectedInfoWindow == infoWindow) {
            selectedInfoWindow = null;
            return;
        }
    }
    //If arrive here, that mean you should open the new info window 
    //because is different from the selected
    selectedInfoWindow = infoWindow;
    selectedInfoWindow.open(map, marker);
});
IgniteCoders
la source
0

Vous devez garder une trace de votre précédent objet InfoWindow et appeler la méthode close dessus lorsque vous gérez l'événement Click sur un nouveau marqueur .

NB Il n'est pas nécessaire d'appeler close sur l'objet de la fenêtre d'information partagée, appeler open avec un marqueur différent fermera automatiquement l'original. Voir la réponse de Daniel pour plus de détails.

RougeBlueThing
la source
Je sais que c'est une vieille réponse, et l'API v3 était obscure à l'époque ... Mais en fait, il n'est pas nécessaire d'appeler la close()méthode, si un seul InfoWindowobjet est utilisé. Il se fermera automatiquement si la open()méthode est à nouveau appelée sur le même objet.
Daniel Vassallo
@ daniel-vassallo Merci pour la note :) J'ai voté pour votre réponse en conséquence, c'est la plus utile, je pense.
RedBlueThing
0

Fondamentalement, vous voulez une fonction qui garde la référence à une new InfoBox()=> déléguez l'événement onclick. Lors de la création de vos marqueurs (en boucle), utilisezbindInfoBox(xhr, map, marker);

// @param(project): xhr : data for infoBox template
// @param(map): object : google.maps.map
// @param(marker): object : google.maps.marker
bindInfoBox: (function () {
    var options = $.extend({}, cfg.infoBoxOptions, { pixelOffset: new google.maps.Size(-450, -30) }),
        infoBox = new window.InfoBox(options);

    return function (project, map, marker) {
        var tpl = renderTemplate(project, cfg.infoBoxTpl); // similar to Mustache, Handlebars

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

var infoBoxest attribué de façon asynchrone et conservé en mémoire. Chaque fois que vous appelezbindInfoBox() la fonction return sera appelée à la place. Aussi pratique pour passer la infoBoxOptionsseule fois!

Dans mon exemple, j'ai dû ajouter un paramètre supplémentaire au mapcar mon initialisation est retardée par les événements de l'onglet.

InfoBoxOptions

Tim Vermaelen
la source
0

Voici une solution qui n'a pas besoin de créer une seule infoWindow pour la réutiliser. Vous pouvez continuer à créer de nombreuses infoWindows, la seule chose dont vous avez besoin est de créer une fonction closeAllInfoWindows et de l'appeler avant d'ouvrir une nouvelle infowindow. Donc, en gardant votre code, il vous suffit de:

  1. Créer un tableau global pour stocker toutes les infoWindows

    var infoWindows = [];
    
  2. Stockez chaque nouvelle infoWindow dans le tableau, juste après infoWindow = new ...

    infoWindows.push(infoWindow);
    
  3. Créer la fonction closeAllInfoWindows

    function closeAllInfoWindows() {
        for (var i=0;i<infoWindows.length;i++) {
            infoWindows[i].close();
        }
    }
    
  4. Dans votre code, appelez closeAllInfoWindows () juste avant d'ouvrir le fichier infoWindow.

Cordialement,

Jortx
la source
-1

Résolu de cette façon:

function window(content){
    google.maps.event.addListener(marker,'click', (function(){
        infowindow.close();
        infowindow = new google.maps.InfoWindow({
            content: content
        });
        infowindow.open(map, this);
    }))
}
window(contentHtml);
Bilal Boulaich
la source
-4

Google Maps vous permet de n'avoir qu'une seule fenêtre d'information ouverte. Donc, si vous ouvrez une nouvelle fenêtre, l'autre se ferme automatiquement.

Kimmo Puputti
la source
2
ce n'est pas correct, je peux ouvrir jusqu'à 20 infowindows sur ma carte. c'est v3 btw.
leo
D'accord, merci pour la correction. Je ne savais pas que cela avait changé dans la version 3.
Kimmo Puputti