javascript - around - google maps setcenter




Google Maps API v3: ¿puedo configurarZoom después de fitBounds? (16)

Tengo un conjunto de puntos que quiero trazar en un mapa de Google incrustado (API v3). Me gustaría que los límites se ajusten a todos los puntos a menos que el nivel de zoom sea demasiado bajo (es decir, se aleje demasiado). Mi enfoque ha sido así:

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

gmap.fitBounds(bounds); 
gmap.setZoom( Math.max(6, gmap.getZoom()) );

Esto no funciona La última línea "gmap.setZoom ()" no cambia el nivel de zoom del mapa si se llama directamente después de fitBounds.

¿Hay alguna manera de obtener el nivel de zoom de un límite sin aplicarlo al mapa? Otras ideas para resolver esto?


Acabo de solucionar esto configurando maxZoom por adelantado, y luego lo eliminé después. Por ejemplo:

map.setOptions({ maxZoom: 15 });
map.fitBounds(bounds);
map.setOptions({ maxZoom: null });

Como yo, si no estás dispuesto a jugar con los oyentes, esta es una solución simple que surgió: agrega un método en el mapa que funcione estrictamente de acuerdo con tus requisitos como este:

    map.fitLmtdBounds = function(bounds, min, max){
        if(bounds.isEmpty()) return;
        if(typeof min == "undefined") min = 5;
        if(typeof max == "undefined") max = 15;

        var tMin = this.minZoom, tMax = this.maxZoom;
        this.setOptions({minZoom:min, maxZoom:max});
        this.fitBounds(bounds);
        this.setOptions({minZoom:tMin, maxZoom:tMax});
    }

luego puede llamar a map.fitLmtdBounds(bounds) lugar de map.fitBounds(bounds) para establecer los límites bajo el rango de zoom definido ... o map.fitLmtdBounds(bounds,3,5) para anular el rango de zoom.


En esta función, debe agregar metadatos dinámicamente para almacenar el tipo de geometría solo porque la función acepta cualquier geometría.

"fitGeometries" es una función JSON que extiende un objeto de mapa.

"geometries" es una matriz genérica de javascript que no es una MVCArray ().

geometry.metadata = { type: "point" };
var geometries = [geometry];

fitGeometries: function (geometries) {
    // go and determine the latLngBounds...
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0; i < geometries.length; i++) {
        var geometry = geometries[i];
        switch (geometry.metadata.type)
        {
            case "point":
                var point = geometry.getPosition();
                bounds.extend(point);
                break;
            case "polyline":
            case "polygon": // Will only get first path
                var path = geometry.getPath();
                for (var j = 0; j < path.getLength(); j++) {
                    var point = path.getAt(j);
                    bounds.extend(point);
                }
                break;
        }
    }
    this.getMap().fitBounds(bounds);
},

He encontrado una solución que hace el control antes de llamar a fitBounds para que no se fitBounds y de repente fitBounds

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

var minLatSpan = 0.001;
if (bounds.toSpan().lat() > minLatSpan) {
    gmap.fitBounds(bounds); 
} else {
    gmap.setCenter(bounds.getCenter());
    gmap.setZoom(16);
}

Tendrás que jugar un poco con la variable minLatSpan para llegar a donde quieras. Variará según el nivel de zoom y las dimensiones del lienzo del mapa.

También puedes usar la longitud en lugar de la latitud


Lo uso para asegurar que el nivel de zoom no exceda un nivel establecido para que sepa que las imágenes de satélite estarán disponibles.

Agregue un oyente al evento zoom_changed . Esto tiene la ventaja adicional de controlar el control del zoom en la IU también.

setZoom si lo necesita, por lo que una sentencia if es preferible a Math.max o Math.min

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() > 19 ) { 
        map.setZoom(19); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

Para evitar el acercamiento demasiado lejos:

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() < 6 ) { 
        map.setZoom(6); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

No me gusta sugerirlo, pero si debe intentarlo, primero llame

gmap.fitBounds(bounds);

A continuación, cree un nuevo Thread / AsyncTask, duerma de 20 a 50 ms o menos y luego llame

gmap.setZoom( Math.max(6, gmap.getZoom()) );

desde el hilo de la interfaz de usuario (use un controlador o el método onPostExecute para AsyncTask).

No sé si funciona, solo una sugerencia. Aparte de eso, debe calcular de alguna manera el nivel de zoom de sus puntos, comprobar si es demasiado bajo, corregirlo y luego simplemente llamar a gmap.setZoom(correctedZoom)


Para responder a otra solución, descubrí que el enfoque "escuchar para el evento bounds_changed y luego establecer el nuevo zoom" no funcionaba de manera confiable para mí. Creo que a veces estaba llamando a fitBounds antes de que el mapa se hubiera inicializado por completo, y la inicialización estaba causando un evento bounds_changed que consumiría al oyente, antes de que fitBounds cambiara los límites y el nivel de acercamiento. Terminé con este código, que parece funcionar hasta ahora:

// If there's only one marker, or if the markers are all super close together,
// `fitBounds` can zoom in too far. We want to limit the maximum zoom it can
// use.
//
// `fitBounds` is asynchronous, so we need to wait until the bounds have
// changed before we know what the new zoom is, using an event handler.
//
// Sometimes this handler gets triggered by a different event, before
// `fitBounds` takes effect; that particularly seems to happen if the map
// hasn't been fully initialized yet. So we don't immediately remove the
// listener; instead, we wait until the 'idle' event, and remove it then.
//
// But 'idle' might happen before 'bounds_changed', so we can't set up the
// removal handler immediately. Set it up in the first event handler.

var removeListener = null;
var listener = google.maps.event.addListener(map, 'bounds_changed', () => {
  console.log(map.getZoom());
  if (map.getZoom() > 15) {
    map.setZoom(15);
  }

  if (!removeListener) {
    removeListener = google.maps.event.addListenerOnce(map, 'idle', () => {
      console.log('remove');
      google.maps.event.removeListener(listener);
    });
  }
});

Por favor intente esto:

map.fitBounds(bounds);

// CHANGE ZOOM LEVEL AFTER FITBOUNDS
zoomChangeBoundsListener = google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
  if (this.getZoom()){
    this.setZoom(15);
  }
});
setTimeout(function(){
  google.maps.event.removeListener(zoomChangeBoundsListener)
}, 2000);

Resolví un problema similar en una de mis aplicaciones. Estaba un poco confundido por tu descripción del problema, pero creo que tienes el mismo objetivo que tenía ...

En mi aplicación, quería trazar uno o más marcadores y asegurarme de que el mapa los mostraba todos. El problema era que, si confiaba únicamente en el método fitBounds, entonces el nivel de zoom se agotaría cuando hubiera un solo punto, eso no era bueno.

La solución era usar fitBounds cuando había muchos puntos, y setCenter + setZoom cuando solo había un punto.

if (pointCount > 1) {
  map.fitBounds(mapBounds);
}
else if (pointCount == 1) {
  map.setCenter(mapBounds.getCenter());
  map.setZoom(14);
}

Si 'bounds_changed' no se activa correctamente (a veces Google no parece aceptar las coordenadas a la perfección), entonces considere usar 'center_changed' en su lugar.

El evento 'center_changed' se dispara cada vez que se llama a fitBounds (), aunque se ejecuta inmediatamente y no necesariamente después de que se haya movido el mapa.

En casos normales, 'inactivo' sigue siendo el mejor detector de eventos, pero esto puede ayudar a un par de personas a tener problemas extraños con sus llamadas fitBounds ().

Ver google maps fitBounds devolución de llamada


Todo lo que hice fue:

map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));

Y funciona en la API V3.


Tuve el mismo problema y pude resolverlo usando el siguiente código. Este evento listener ( google.maps.addListenerOnce() ) solo se activará una vez, justo después de que se map.fitBounds() . Entonces, no hay necesidad de

  1. Mantenga un registro y elimine manualmente al oyente, o
  2. Espere hasta que el mapa esté idle .

Establece el nivel de zoom apropiado inicialmente y permite al usuario acercar y alejar el nivel de zoom inicial porque el detector de eventos ha expirado. Por ejemplo, si solo se llamara google.maps.addListener() , el usuario nunca podría hacer zoom más allá del nivel de zoom indicado (en el caso, 4). Desde que implementamos google.maps.addListenerOnce() , el usuario podrá hacer zoom a cualquier nivel que elija.

map.fitBounds(bounds);

var zoom_level_for_one_marker = 4;

google.maps.event.addListenerOnce(map, 'bounds_changed', function(event){
   if (this.getZoom() >= zoom_level_for_one_marker){  
       this.setZoom(zoom_level_for_one_marker) 
   }
});

Vi muchas soluciones incorrectas o demasiado complicadas, así que decidí publicar una solución elegante y funcional .

El motivo por el que setZoom() no funciona como espera es que fitBounds() sea ​​asincrónico, por lo que no garantiza que actualice inmediatamente el zoom, pero su llamada a setZoom() depende de eso.

Lo que podría considerar es establecer la opción del mapa minZoom antes de llamar a fitBounds() y luego fitBounds() después de que se complete (para que los usuarios puedan hacer zoom de forma manual si así lo desean):

var bounds = new google.maps.LatLngBounds();
// ... (extend bounds with all points you want to fit)

// Ensure the map does not get too zoomed out when fitting the bounds.
gmap.setOptions({minZoom: 6});
// Clear the minZoom only after the map fits the bounds (note that
// fitBounds() is asynchronous). The 'idle' event fires when the map
// becomes idle after panning or zooming.
google.maps.event.addListenerOnce(gmap, 'idle', function() {
  gmap.setOptions({minZoom: null});
});

gmap.fitBounds(bounds);

Además, si también quiere limitar el zoom máximo, puede aplicar el mismo truco con la propiedad maxZoom .

Vea los documentos de MapOptions .


Yo suelo:

gmap.setZoom(24); //this looks a high enough zoom value
gmap.fitBounds(bounds); //now the fitBounds should make the zoom value only less

Esto utilizará el menor de 24 y el nivel de zoom necesario de acuerdo con su código, sin embargo, probablemente cambie el zoom de todos modos y no le importe cuánto se alejó.


Editar : vea el comentario de Matt Diamond a continuación.

¡Lo tengo! Prueba esto:

map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() { 
  if (map.getZoom() > 16) map.setZoom(16); 
  google.maps.event.removeListener(listener); 
});

Modifique a sus necesidades.


google.maps.event.addListener(marker, 'dblclick', function () {
    var oldZoom = map.getZoom(); 
    map.setCenter(this.getPosition());
    map.setZoom(parseInt(oldZoom) + 1);
});




fitbounds