2012-10-10 12 views
6

Tengo un conjunto dinámico de teselas donde NO deseo permitir el cribado fuera de sus límites.Mapa de google dinámico con mosaicos personalizados para evitar que se repita la panorámica

El código de abajo me pone cerca, pero el usuario puede desplazarse horizontalmente fuera de los límites estrictos, ya que utiliza el centro del mapa para la comparación

var strictBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(sw_lat, sw_lon), 
new google.maps.LatLng(ne_lat, ne_lon) 
); 

google.maps.event.addListener(map, 'drag', function() 
{ 
    if (strictBounds.contains(map.getCenter())) return; 

// We're out of bounds - Move the map back within the bounds 

var c = map.getCenter(), 
    x = c.lng(), 
    y = c.lat(), 
    maxX = strictBounds.getNorthEast().lng(), 
    maxY = strictBounds.getNorthEast().lat(), 
    minX = strictBounds.getSouthWest().lng(), 
    minY = strictBounds.getSouthWest().lat(); 

if (x < minX) x = minX; 
if (x > maxX) x = maxX; 
if (y < minY) y = minY; 
if (y > maxY) y = maxY; 

map.setCenter(new google.maps.LatLng(y, x)); 
}); 

What is happening

What I want

+1

puede proporcionar alguna información o bien si una de las respuestas que aquí trabajaron para usted? – Tiborg

Respuesta

0

En lugar de utilizar map.getCenter() como verificación, use map.getBounds()

No probado, pero es una forma simple de lograr t la suya sería para comprobar si la unión de ambos límites eran idénticos (si no, sus límites mapa es fuera de sus límites estrictos):

var union = strictBounds.union(map.getBounds()); 
if (strictBounds.equals(union)) { //new map bounds is within strict bounds 
9

Para un acceso rápido, aquí es el jsFiddle para esta solución: http://jsfiddle.net/nYz6k/


Suponiendo que esté satisfecho con la solución actual de detección de límites contra el centro, todo lo que tiene que hacer es restringir los límites en función del tamaño del lienzo del mapa actual.

El resultado que está obteniendo ahora es que cada esquina de los límites restrictivos aparece en el centro del mapa cuando es de restricción total (es decir, tanto la latitud como la longitud superan las esquinas de los límites).

La solución es eliminar realmente el desplazamiento xey de los límites, y aún así poder verificar contra el centro (que es la solución más eficiente, en comparación con otras soluciones de control basadas en límites).

Además, debe restringir los límites solo cuando inicializa el mapa y cuando se cambia el tamaño de la ventana, lo que significa que cuando navega no hay gastos adicionales de procesamiento además del método de comprobación que ya ha proporcionado.

No se olvide de establecer la propiedadMaxZoom para el mapa (ajustar según sea necesario), ya que por encima de un determinado nivel de zoom de los límites que restringen serán por sí mismos encajar en la vista y no hay solución para eso.

¡Importante! Use 'center_changed' en lugar de 'arrastrar' porque 'drag' tiene ese comportamiento de deslizamiento que cuando termina de arrastrar y establecer el centro, los mapas todavía se deslizan en la dirección de la panorámica.


Antes de implementar la solución le recomiendo que echa un vistazo a cómo coordinar la API de Google Maps funciona el sistema y de proyección, ya que esta solución se basa principalmente en él, y si desea modificar a cabo, es útil conoce esta información

https://developers.google.com/maps/documentation/javascript/maptypes y revise los Tipos de mapas personalizados -> Coordenadas del mapa sección.


Esto es lo que necesita hacer. En primer lugar, debe implementar 2 métodos cortos de conversión entre coordenadas geográficas (LatLng) y coordenadas de píxeles.

var fromLatLngToPixel = function (latLng) { 
    var point = map.getProjection().fromLatLngToPoint(latLng); 
    var zoom = map.getZoom(); 
    return new google.maps.Point(
    Math.floor(point.x * Math.pow(2, zoom)), 
    Math.floor(point.y * Math.pow(2, zoom)) 
); 
} 

var fromPixelToLatLng = function (pixel) { 
    var zoom = map.getZoom(); 
    var point = new google.maps.Point(
    pixel.x/Math.pow(2, zoom), 
    pixel.y/Math.pow(2, zoom) 
); 
    return map.getProjection().fromPointToLatLng(point); 
} 

A continuación, implemente el método que restringe efectivamente los límites. Tenga en cuenta que siempre debe mantener una variable que almacena los límites originales, ya que cada vez que se cambie el tamaño del lienzo del mapa, los límites resultantes cambiarán.

Para esto, digamos originalBounds mantiene los límites que nos ha facilitado con sw_lat, sw_long etc, y shrinkedBounds se modifica mediante este método. Puede cambiarle el nombre a strictBounds para que siga funcionando en su método, pero depende de usted. Utiliza jQuery para obtener el ancho y alto del objeto canvas.

var shrinkBounds = function() { 
    zoom = map.getZoom(); 

    // The x and y offset will always be half the current map canvas 
    // width and height respectively 
    xoffset = $('#map_canvas').width()/2; 
    yoffset = $('#map_canvas').height()/2; 

    // Convert the bounds extremities to global pixel coordinates 
    var pixswOriginal = fromLatLngToPixel(originalBounds.getSouthWest()); 
    var pixneOriginal = fromLatLngToPixel(originalBounds.getNorthEast()); 

    // Shrink the original bounds with the x and y offset 
    var pixswShrinked = new google.maps.Point(pixswOriginal.x + xoffset, pixswOriginal.y - yoffset); 
    var pixneShrinked = new google.maps.Point(pixneOriginal.x - xoffset, pixneOriginal.y + yoffset); 

    // Rebuild the shrinkedBounds object with the modified 
    shrinkedBounds = new google.maps.LatLngBounds(
    fromPixelToLatLng(pixswShrinked), 
    fromPixelToLatLng(pixneShrinked)); 
} 

A continuación, todo lo que tiene que hacer es llamar a este método:

  • una vez cuando el mapa se ha inicializado. Tenga en cuenta que, dependiendo de cuándo llame al método, es posible que obtenga algunos errores extraños, ya que es posible que el mapa aún no haya inicializado todas sus propiedades. La mejor forma es usar el evento projection_changed.

    google.maps.event.addListener(map, 'projection_changed', function (e) { 
        shrinkBounds(); 
    }); 
    
  • cada vez que la vista del mapa se cambia el tamaño

    google.maps.event.addListener(map, 'resize', function (e) { 
        shrinkBounds(); 
    }); 
    

Pero la parte más importante de esto es que el evento 'redimensionar' nunca se desencadena por redimensiona programáticos del mapa contenedor, por lo que debe desencadenarlo manualmente cada vez que cambie el tamaño del lienzo de forma programática (si lo hace, pero dudo que lo haga).

La forma más común es poner en funcionamiento cuando la ventana es redimensionada:

$(window).resize(function() { 
    google.maps.event.trigger(map, 'resize'); 
}); 

Después de todo esto, ahora se puede utilizar con seguridad su método, sino como un controlador para 'center_changed' y no para " arrastre 'como he mencionado anteriormente.


Configuré un jsfiddle con el código de trabajo completo.

http://jsfiddle.net/nYz6k/

se puede ver la restricción en la esquina inferior izquierda con esa pequeña media marcador que aparece, que se coloca en la esquina suroeste de los límites. También hay uno en la esquina noroeste pero, naturalmente, no puedes verlo porque se muestra encima de la posición.

versión
0

Tiborg anterior es la mejor versión hasta ahora en mantener los límites ... me di cuenta de un error que se produce cuando el nivel de zoom y la anchura/altura son más grandes que los límites originales

he modificado su código y añadido un rectángulo para verlo en acción.

var buildBounds = function(sw, ne) { 
    var swY = sw.lat(); 
    var swX = sw.lng(); 
    var neY = ne.lat(); 
    var neX = ne.lng(); 
    if (swY > neY) { 
     var cY = (swY + neY)/2; 
     swY = cY; 
     neY = cY; 
    } 
    if (swX > neX) { 
     var cX = (swX + neX)/2; 
     swX = cX; 
     neX = cX; 
    } 
    return new google.maps.LatLngBounds(
     new google.maps.LatLng(swY, swX), 
     new google.maps.LatLng(neY, neX)); 
    } 

http://jsfiddle.net/p4wgjs6s/

Cuestiones relacionadas