Abra apenas uma InfoWindow na API do Google Maps v3

85

Eu preciso ter apenas uma InfoWindow aberta no meu mapa do Google. Preciso fechar todas as outras InfoWindows antes de abrir uma nova.

Alguém pode me mostrar como fazer isso?

Leo
fonte
O que você tentou?
IgniteCoders

Respostas:

152

Você precisa criar apenas um InfoWindowobjeto, manter uma referência a ele e reutilizá-lo para todos os marcadores. Citação do Google Maps API Docs :

Se você deseja que apenas uma janela de informações seja exibida por vez (como é o comportamento no Google Maps), você só precisa criar uma janela de informações, que pode ser reatribuída a diferentes locais ou marcadores nos eventos do mapa (como cliques do usuário).

Portanto, você pode simplesmente criar o InfoWindowobjeto logo após inicializar seu mapa e, em seguida, manipular os clickmanipuladores de eventos de seus marcadores da seguinte maneira. Digamos que você tenha um marcador chamado someMarker:

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

Então, o InfoWindowdeve fechar automaticamente quando você clica em um novo marcador sem ter que chamar o close()método.

Daniel Vassallo
fonte
Eu também faço isso, mas é normal que a infoWindow demore cerca de +1 segundo para abrir no próximo marcador? às vezes, ele nem abre. Eu uso exatamente o mesmo código
MJB
Daniel, ótima ideia !! antes disso, eu estava tentando sincronizar manualmente, mas mostra erros de javascript estranhos (como "c é nulo" em main.js ou algo como (123 fora do intervalo 43)).
Victor
31

Crie sua janela de informações fora do escopo para que você possa compartilhá-la.

Aqui está um exemplo simples:

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
fonte
Obrigado. Usar "isso" resolveu a maioria dos meus problemas. Ainda não entendo como usar conteúdo personalizado dentro de setContent. Por exemplo, em meu loop de marcador, eu crio uma variável contentHtml usando a variável "i" e vinculando-a a um objeto de banco de dados. Como posso passar essa variável contentHtml para o ouvinte?
Ryan,
No meu caso, a janela só abre quando uso "this" em infowindow.open (map, this); Em vez de "marcador". Obrigado por compartilhar sua solução.
possuindo
Eu também faço isso, mas é normal que a infoWindow demore cerca de +1 segundo para abrir no próximo marcador? às vezes nem abre. Eu uso exatamente o mesmo código
MJB
14

Eu tive o mesmo problema, mas a melhor resposta não resolveu completamente, o que eu tive que fazer na minha instrução for foi usar o this relacionado ao meu marcador atual. Talvez isso ajude alguém.

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
fonte
2
A maneira como você passa o contentString foi útil para mim, obrigado.
possuir em
5

um pouco tarde, mas consegui ter apenas uma janela de informações aberta por maken infowindow uma variável global.

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

então dentro do listner

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

infowindow.open(map, this);
user2827958
fonte
1
Funciona muito bem para mim :)
lumos
4

Declare um globar var selectedInfoWindow;e use-o para manter a janela de informações aberta:

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
fonte
0

Você precisa manter o controle de seu objeto InfoWindow anterior e chamar o método close nele ao manipular o evento click em um novo marcador .

NB: não é necessário chamar close no objeto da janela de informações compartilhada, chamar open com um marcador diferente fechará automaticamente o original. Veja a resposta de Daniel para detalhes.

RedBlueThing
fonte
Eu sei que esta é uma resposta antiga, e a API v3 era obscura na época ... Mas na verdade não há necessidade de chamar o close()método, se um único InfoWindowobjeto for usado. Ele será fechado automaticamente se o open()método for chamado novamente no mesmo objeto.
Daniel Vassallo
@ daniel-vassallo Obrigado pela nota :) Votei positivamente em sua resposta, acho que é a mais útil.
RedBlueThing
0

Basicamente, você deseja uma função que mantenha referência a um new InfoBox()=> delegar o evento onclick. Ao criar seus marcadores (em um loop), usebindInfoBox(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 infoBoxé atribuído de forma assíncrona e mantido na memória. Cada vez que você chamar, bindInfoBox()a função de retorno será chamada. Também útil para passar infoBoxOptionsapenas uma vez!

No meu exemplo, tive que adicionar um parâmetro extra ao, mappois minha inicialização é atrasada por eventos de guia.

InfoBoxOptions

Tim Vermaelen
fonte
0

Aqui está uma solução que não precisa criar apenas uma infoWindow para reutilizá-la. Você pode continuar criando muitas infoWindows, a única coisa que você precisa é construir uma função closeAllInfoWindows e chamá-la antes de abrir uma nova janela de informações. Portanto, mantendo seu código, você só precisa:

  1. Crie uma matriz global para armazenar todas as infoWindows

    var infoWindows = [];
    
  2. Armazene cada nova infoWindow na matriz, logo após a infoWindow = new ...

    infoWindows.push(infoWindow);
    
  3. Crie a função closeAllInfoWindows

    function closeAllInfoWindows() {
        for (var i=0;i<infoWindows.length;i++) {
            infoWindows[i].close();
        }
    }
    
  4. Em seu código, chame para closeAllInfoWindows () antes de abrir o infoWindow.

Saudações,

Jortx
fonte
Funciona, mas não é uma solução muito boa porque você continua adicionando janelas de informações ao array, então há a possibilidade de ter um array com muitas ocorrências da mesma janela de informações.
Wally
-1

Resolvido desta forma:

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
fonte
-5

O Google Maps permite que você tenha apenas uma janela de informações aberta. Portanto, se você abrir uma nova janela, a outra será fechada automaticamente.

Kimmo Puputti
fonte
2
isso não está certo, posso abrir até 20 janelas de informações no meu mapa. é v3 btw.
leo
Ok, obrigado por corrigir. Não sabia que havia mudado na versão 3.
Kimmo Puputti