javascript leaflet - Google Maps API v3:¿puedo configurarZoom después de fitBounds?




center around (20)

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?


Answers

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


Para mí, la solución más fácil fue esta:

map.fitBounds(bounds);

function set_zoom() {
    if(map.getZoom()) {map.setZoom(map.getZoom() - 1);}
    else {setTimeout(set_zoom, 5);}
}
setTimeout(set_zoom, 5);

Tuve el mismo problema, necesario para adaptarse a muchos marcadores en el mapa. Esto resolvió mi caso:

  1. Declarar límites
  2. Utilice el esquema proporcionado por koderoid (para cada conjunto de marcadores bounds.extend(objLatLng) )
  3. Ejecutar fitbounds DESPUÉS de completar el mapa:

    google.maps.event.addListenerOnce(map, 'idle', function() { 
        map.fitBounds( bounds );
    });
    

He venido a esta página varias veces para obtener la respuesta, y aunque todas las respuestas existentes fueron muy útiles, no resolvieron mi problema exactamente.

google.maps.event.addListenerOnce(googleMap, 'zoom_changed', function() {
    var oldZoom = googleMap.getZoom();
    googleMap.setZoom(oldZoom - 1); //Or whatever
});

Básicamente, descubrí que el evento 'zoom_changed' impedía que la IU del mapa se "saltara", lo que sucedía cuando esperaba el evento 'inactivo'.

Espero que esto ayude a alguien!


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

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 .


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)


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.


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);
},

Después del cálculo de los límites, puede verificar la distancia entre la esquina superior izquierda y la esquina inferior derecha; entonces usted puede entender el nivel de zoom probando la distancia (si la distancia es demasiado grande, el nivel de zoom sería bajo) luego puede seleccionar si usa el método setbound o setZoom.


Todo lo que hice fue:

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

Y funciona en la API V3.


Si no me equivoco, supongo que quiere que todos sus puntos sean visibles en el mapa con el nivel de zoom más alto posible. Lo logré inicializando el nivel de zoom del mapa en 16 (no estoy seguro de si es el nivel de zoom más alto posible en V3).

var map = new google.maps.Map(document.getElementById('map_canvas'), {
  zoom: 16,
  center: marker_point,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

Luego, después de eso, hice lo de límites:

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

// You can have a loop here of all you marker points
// Begin loop
bounds.extend(marker_point);
// End loop

map.fitBounds(bounds);

Resultado: ¡éxito!


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);
    });
  }
});

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);

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


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ó.


este trabajo es para mí con API v3 pero con la configuración de zoom fijo:

var bounds = new google.maps.LatLngBounds();
// extend bounds with each point

gmap.setCenter(bounds.getCenter()); 
gmap.setZoom( 6 );

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);
}

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 });

Usar JQuery sería bueno;

<a href="#" id="youLink">Call JavaScript </a>



$("#yourLink").click(function(e){
//do what ever you want...
});






javascript google-maps google-maps-api-3 fitbounds