Centralizar / definir o zoom do mapa para cobrir todos os marcadores visíveis?

352

Estou definindo vários marcadores no meu mapa e posso definir estaticamente os níveis de zoom e o centro, mas o que eu quero é cobrir todos os marcadores e aplicar o zoom o máximo possível, com todos os mercados visíveis

Os métodos disponíveis estão seguindo

setZoom(zoom:number)

e

setCenter(latlng:LatLng)

Não setCentersuporta entrada múltipla de localização ou matriz de localização nem setZoompossui esse tipo de funcionalidade

insira a descrição da imagem aqui

Trikaldarshi
fonte
você precisa adicionar o latlnga um boundsobjeto cada vez que você adicionar um marcador e definir o seu mapa para encaixar os limites finais. Veja a resposta aqui: stackoverflow.com/questions/1556921/…
Suvi Vignarajah 10/10

Respostas:

678

Você precisa usar o fitBounds()método

var markers = [];//some array
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markers.length; i++) {
 bounds.extend(markers[i]);
}

map.fitBounds(bounds);

Documentação de developers.google.com/maps/documentation/javascript :

fitBounds(bounds[, padding])

Parâmetros:

`bounds`:  [`LatLngBounds`][1]|[`LatLngBoundsLiteral`][1]
`padding` (optional):  number|[`Padding`][1]

Valor de retorno: Nenhum

Define a viewport para conter os limites especificados.
Nota : Quando o mapa está definido como display: none, a fitBoundsfunção lê o tamanho do mapa como 0x0e, portanto, não faz nada. Para alterar a viewport enquanto o mapa está oculto, defina o mapa como visibility: hidden, garantindo assim que a div do mapa tenha um tamanho real.

Adão
fonte
3
De onde veio o getPositionmétodo?
Pratheep
6
@Pratheep - faz parte da classe google.maps.Marker; developers.google.com/maps/documentation/javascript/…
Adam
Trabalhou como um encanto! Graças
Joseph N.
9
Apenas como um aparte para os novatos por aí, com a mesma pergunta do Pratheep ... Você sabe disso se tiver experiência com a API do Google Maps, mas sempre pode passar LatLngLiteraluma instância em vez de ter uma Marker. por exemplo bounds.extend({lat: 123, lng: 456}),.
Kyle Baker
11
Uma dica extra para qualquer pessoa interessada. Você pode definir um preenchimento usando o fitBounds(bounds, int)que permitirá que você tenha um pouco de espaço entre os marcadores e as bordas do mapa (ou menos espaço, se necessário). Veja a documentação
MickelsonMichael
178

Para estender a resposta fornecida com alguns truques úteis:

var markers = //some array;
var bounds = new google.maps.LatLngBounds();
for(i=0;i<markers.length;i++) {
   bounds.extend(markers[i].getPosition());
}

//center the map to a specific spot (city)
map.setCenter(center); 

//center the map to the geometric center of all markers
map.setCenter(bounds.getCenter());

map.fitBounds(bounds);

//remove one zoom level to ensure no marker is on the edge.
map.setZoom(map.getZoom()-1); 

// set a minimum zoom 
// if you got only 1 marker or all markers are on the same address map will be zoomed too much.
if(map.getZoom()> 15){
  map.setZoom(15);
}

//Alternatively this code can be used to set the zoom for just 1 marker and to skip redrawing.
//Note that this will not cover the case if you have 2 markers on the same address.
if(count(markers) == 1){
    map.setMaxZoom(15);
    map.fitBounds(bounds);
    map.setMaxZoom(Null)
}

ATUALIZAÇÃO:
pesquisas adicionais no tópico mostram que fitBounds () é assíncrono e é melhor fazer a manipulação do zoom com um ouvinte definido antes de chamar Fit Bounds.
Obrigado @Tim, @ xr280xr, mais exemplos sobre o tópico: SO: setzoom-after-fitbounds

google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
  this.setZoom(map.getZoom()-1);

  if (this.getZoom() > 15) {
    this.setZoom(15);
  }
});
map.fitBounds(bounds);
d.raev
fonte
4
Boas adições. Obrigado!
Paneer_tikka
11
Eu estava tendo undefined retornado por .getZoom (). Esta resposta me ajudou a resolvê-lo usando addListenerOnceon zoom_changedpara definir o zoom depois que seu valor foi inicializado.
Xr280xr 18/09/2015
11
Obrigado @ d.raev, mas definir o zoom máximo quando os limites já estão definidos não funciona. O que você deve fazer é definir a opção "maxZoom" ao inicializar seu mapa. developers.google.com/maps/documentation/javascript/…
Tim
11
Na parte sobre a manipulação do zoom ( UPDATE ), você está misturando alguns vars e escopos. Você usa yourMap, mape this. Talvez seja uma boa ideia torná-lo mais consistente.
Gustavo Straube
11

O tamanho da matriz deve ser maior que zero. Caso contrário, você terá resultados inesperados.

function zoomeExtends(){
  var bounds = new google.maps.LatLngBounds();
  if (markers.length>0) { 
      for (var i = 0; i < markers.length; i++) {
         bounds.extend(markers[i].getPosition());
        }    
        myMap.fitBounds(bounds);
    }
}
Fotis. Tsilfoglou
fonte
8

Existe este MarkerClustererutilitário do lado do cliente disponível para o Google Map, conforme especificado aqui nos artigos para desenvolvedores do Google Map . Aqui está um resumo do que é seu uso:

Existem muitas abordagens para fazer o que você pediu:

  • Cluster baseado em grade
  • Cluster baseado em distância
  • Gerenciamento de marcadores de viewport
  • Mesas de fusão
  • Marcador de cluster
  • MarkerManager

Você pode ler sobre eles no link fornecido acima.

Marker Clustererusa cluster baseado em grade para agrupar todo o marcador que deseja a grade. O agrupamento baseado em grade funciona dividindo o mapa em quadrados de um determinado tamanho (o tamanho muda a cada zoom) e, em seguida, agrupando os marcadores em cada quadrado da grade.

Antes de agrupar Antes de agrupar

Após o Clustering Após o Clustering

Espero que seja isso o que você estava procurando e isso resolva o seu problema :)

iyogeshjoshi
fonte