Saltar al contenido

Google Maps V3 – Cómo calcular el nivel de zoom para un límite dado

No dudes en compartir nuestro sitio y códigos con tus amigos, apóyanos para aumentar nuestra comunidad.

Solución:

Gracias a Giles Gardam por su respuesta, pero solo aborda la longitud y no la latitud. Una solución completa debería calcular el nivel de zoom necesario para la latitud y el nivel de zoom necesario para la longitud, y luego tomar el más pequeño (más alejado) de los dos.

Aquí hay una función que usa tanto la latitud como la longitud:

function getBoundsZoomLevel(bounds, mapDim) 
    var WORLD_DIM =  height: 256, width: 256 ;
    var ZOOM_MAX = 21;

    function latRad(lat) 
        var sin = Math.sin(lat * Math.PI / 180);
        var radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
        return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
    

    function zoom(mapPx, worldPx, fraction) 
        return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2);
    

    var ne = bounds.getNorthEast();
    var sw = bounds.getSouthWest();

    var latFraction = (latRad(ne.lat()) - latRad(sw.lat())) / Math.PI;

    var lngDiff = ne.lng() - sw.lng();
    var lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;

    var latZoom = zoom(mapDim.height, WORLD_DIM.height, latFraction);
    var lngZoom = zoom(mapDim.width, WORLD_DIM.width, lngFraction);

    return Math.min(latZoom, lngZoom, ZOOM_MAX);

Demostración en jsfiddle

Parámetros:

El valor del parámetro "límites" debe ser un google.maps.LatLngBounds objeto.

El valor del parámetro "mapDim" debe ser un objeto con propiedades de "alto" y "ancho" que representen el alto y el ancho del elemento DOM que muestra el mapa. Es posible que desee disminuir estos valores si desea garantizar el relleno. Es decir, es posible que no desee que los marcadores de mapa dentro de los límites estén demasiado cerca del borde del mapa.

Si está utilizando la biblioteca jQuery, el mapDim valor se puede obtener de la siguiente manera:

var $mapDiv = $('#mapElementId');
var mapDim =  height: $mapDiv.height(), width: $mapDiv.width() ;

Si está utilizando la biblioteca Prototype, el valor mapDim se puede obtener de la siguiente manera:

var mapDim = $('mapElementId').getDimensions();

Valor de retorno:

El valor devuelto es el nivel de zoom máximo que seguirá mostrando los límites completos. Este valor estará entre 0 y el nivel máximo de zoom, inclusive.

El nivel de zoom máximo es 21. (Creo que solo fue 19 para Google Maps API v2.)


Explicación:

Google Maps utiliza una proyección de Mercator. En una proyección de Mercator, las líneas de longitud están igualmente espaciadas, pero las líneas de latitud no lo están. La distancia entre líneas de latitud aumenta a medida que van del ecuador a los polos. De hecho la distancia tiende hacia el infinito al llegar a los polos. Sin embargo, un mapa de Google Maps no muestra latitudes por encima de aproximadamente 85 grados norte o por debajo de aproximadamente -85 grados sur. (referencia) (Calculo el límite real en +/-85.05112877980658 grados).

Esto hace que el cálculo de las fracciones de los límites sea más complicado para la latitud que para la longitud. Usé una fórmula de Wikipedia para calcular la fracción de latitud. Supongo que esto coincide con la proyección utilizada por Google Maps. Después de todo, la página de documentación de Google Maps a la que vinculo anteriormente contiene un enlace a la misma página de Wikipedia.

Otras notas:

  1. Los niveles de zoom van desde 0 hasta el nivel de zoom máximo. El nivel de zoom 0 es el mapa completamente alejado. Los niveles más altos acercan más el mapa. (referencia)
  2. En el nivel de zoom 0, el mundo entero se puede mostrar en un área de 256 x 256 píxeles. (referencia)
  3. Para cada nivel de zoom más alto, el número de píxeles necesarios para mostrar la misma área se duplica tanto en ancho como en alto. (referencia)
  4. Los mapas se ajustan en la dirección longitudinal, pero no en la dirección latitudinal.

Se ha hecho una pregunta similar en el grupo de Google: http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/e6448fc197c3c892

Los niveles de zoom son discretos, con la escala duplicándose en cada paso. Entonces, en general, no puede ajustarse exactamente a los límites que desea (a menos que tenga mucha suerte con el tamaño del mapa en particular).

Otro problema es la relación entre las longitudes de los lados, por ejemplo, no puede ajustar los límites exactamente a un rectángulo delgado dentro de un mapa cuadrado.

No hay una respuesta fácil sobre cómo ajustar los límites exactos, porque incluso si está dispuesto a cambiar el tamaño de la división del mapa, debe elegir a qué tamaño y el nivel de zoom correspondiente cambia (en términos generales, ¿lo hace más grande o más pequeño? de lo que es actualmente?).

Si realmente necesita calcular el zoom, en lugar de almacenarlo, esto debería funcionar:

La proyección de Mercator deforma la latitud, pero cualquier diferencia de longitud siempre representa la misma fracción del ancho del mapa (la diferencia de ángulo en grados/360). Con el zoom cero, el mapa mundial completo tiene 256x256 píxeles, y al hacer zoom en cada nivel se duplica el ancho y la altura. Entonces, después de un poco de álgebra, podemos calcular el zoom de la siguiente manera, siempre que sepamos el ancho del mapa en píxeles. Tenga en cuenta que debido a que la longitud se envuelve, debemos asegurarnos de que el ángulo sea positivo.

var GLOBE_WIDTH = 256; // a constant in Google's map projection
var west = sw.lng();
var east = ne.lng();
var angle = east - west;
if (angle < 0) 
  angle += 360;

var zoom = Math.round(Math.log(pixelWidth * 360 / angle / GLOBE_WIDTH) / Math.LN2);

Para la versión 3 de la API, esto es simple y funcional:

var latlngList = [];
latlngList.push(new google.maps.LatLng(lat, lng));

var bounds = new google.maps.LatLngBounds();
latlngList.each(function(n) 
    bounds.extend(n);
);

map.setCenter(bounds.getCenter()); //or use custom center
map.fitBounds(bounds);

y algunos trucos opcionales:

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

Aquí tienes las comentarios y valoraciones

Si guardas alguna vacilación y forma de progresar nuestro sección eres capaz de dejar una anotación y con mucho gusto lo leeremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *