2010-10-10 18 views
11

Estoy tratando de establecer los límites donde puede arrastrar el mapa con Google Maps API V3 Aquí está la solución para V2 http://econym.org.uk/gmap/example_range.htm que funciona bastante bien.Google Maps API V3: limite los límites del mapa

Sin embargo, con la API V3 no es tan bueno: cuando se utiliza los mismos checkbounds función(), el mapa se retorcía cuando llegue a la cota mientras map.setCenter() cambia el centro del mapa.

¿Cómo corregirlo? ¿Cuál es la solución para API V3?

Respuesta

19

He tenido el mismo problema, pero esto debería resolverlo (es la misma función, el evento para escuchar ha cambiado de 'mover' o 'arrastrar' a 'center_changed', funciona como un encanto !:

google.maps.event.addListener(map,'center_changed',function() { checkBounds(); }); 

function checkBounds() {  
    if(! allowedBounds.contains(map.getCenter())) { 
     var C = map.getCenter(); 
     var X = C.lng(); 
     var Y = C.lat(); 

     var AmaxX = allowedBounds.getNorthEast().lng(); 
     var AmaxY = allowedBounds.getNorthEast().lat(); 
     var AminX = allowedBounds.getSouthWest().lng(); 
     var AminY = allowedBounds.getSouthWest().lat(); 

     if (X < AminX) {X = AminX;} 
     if (X > AmaxX) {X = AmaxX;} 
     if (Y < AminY) {Y = AminY;} 
     if (Y > AmaxY) {Y = AmaxY;} 

     map.setCenter(new google.maps.LatLng(Y,X)); 
    } 
} 
+0

Lo usé y funciona increíble. ¡Aclamaciones! –

+5

¿cómo se configura 'allowedBounds'? – travis

+1

allowedBounds es un [objeto LatLngBounds] (https://developers.google.com/maps/documentation/javascript/reference#LatLngBounds) (básicamente un par de latitudes/longitudes). Esto funciona muy bien BTW, ¡hace exactamente lo que debería hacer por mí! – strikernl

4

Este script recibe los límites iniciales (allowedBounds) y el límite de los límites de drag y zoom_changed. también el zoom está limitado en < 7.

var allowedBounds = false; 

google.maps.event.addListener(map, 'idle', function() { 
if (!allowedBounds) { 
    allowedBounds = map.getBounds(); 
} 
}); 

google.maps.event.addListener(map, 'drag', checkBounds); 
google.maps.event.addListener(map, 'zoom_changed', checkBounds); 

function checkBounds() { 

if (map.getZoom() < 7) map.setZoom(7); 

if (allowedBounds) { 

    var allowed_ne_lng = allowedBounds.getNorthEast().lng(); 
    var allowed_ne_lat = allowedBounds.getNorthEast().lat(); 
    var allowed_sw_lng = allowedBounds.getSouthWest().lng(); 
    var allowed_sw_lat = allowedBounds.getSouthWest().lat(); 

    var currentBounds = map.getBounds(); 
    var current_ne_lng = currentBounds.getNorthEast().lng(); 
    var current_ne_lat = currentBounds.getNorthEast().lat(); 
    var current_sw_lng = currentBounds.getSouthWest().lng(); 
    var current_sw_lat = currentBounds.getSouthWest().lat(); 

    var currentCenter = map.getCenter(); 
    var centerX = currentCenter.lng(); 
    var centerY = currentCenter.lat(); 

    if (current_ne_lng > allowed_ne_lng) centerX = centerX-(current_ne_lng-allowed_ne_lng); 
    if (current_ne_lat > allowed_ne_lat) centerY = centerY-(current_ne_lat-allowed_ne_lat); 
    if (current_sw_lng < allowed_sw_lng) centerX = centerX+(allowed_sw_lng-current_sw_lng); 
    if (current_sw_lat < allowed_sw_lat) centerY = centerY+(allowed_sw_lat-current_sw_lat); 

    map.setCenter(new google.maps.LatLng(centerY,centerX)); 
} 
} 
+0

Esta es la única respuesta que he encontrado que toma en consideración los límites exteriores y no solo el centro. Confiar solo en el centro le permite desplazarse bien fuera de un área prevista, dependiendo del nivel de zoom. – James

1

Gracias @sairafi. Su respuesta me puso muy cerca. Estaba getti Encontré un error donde getBounds no estaba definido, así que lo envolví en otro oyente para asegurarme de que el mapa estaba completamente cargado primero.

google.maps.event.addListenerOnce(map, 'tilesloaded', function() { 
    allowedBounds = map.getBounds(); 
    google.maps.event.addListener(map,'center_changed',function() { checkBounds(allowedBounds); }); 
}); 

// Limit map area 
function checkBounds(allowedBounds) { 

if(!allowedBounds.contains(map.getCenter())) { 
    var C = map.getCenter(); 
    var X = C.lng(); 
    var Y = C.lat(); 

    var AmaxX = allowedBounds.getNorthEast().lng(); 
    var AmaxY = allowedBounds.getNorthEast().lat(); 
    var AminX = allowedBounds.getSouthWest().lng(); 
    var AminY = allowedBounds.getSouthWest().lat(); 

    if (X < AminX) {X = AminX;} 
    if (X > AmaxX) {X = AmaxX;} 
    if (Y < AminY) {Y = AminY;} 
    if (Y > AmaxY) {Y = AmaxY;} 

    map.setCenter(new google.maps.LatLng(Y,X)); 
} 
} 
0
southWest = new google.maps.LatLng(48.59475380744011,22.247364044189453); 
      northEast = new google.maps.LatLng(48.655344320891444,22.352420806884766); 
      var limBound = new google.maps.LatLngBounds(southWest,northEast); 
      var lastCenter; 

      var option = {zoom:15, 
      center: limBound.getCenter(), 
      mapTypeId: google.maps.MapTypeId.ROADMAP}; 
      var map = new google.maps.Map(document.getElementById('divMap'),option); 
      google.maps.event.addListener(map,'zoom_changed', function() { 
       minZoom(15); 
       }); 
      google.maps.event.addListener(map,'drag',function(e){ 
       limitBound(limBound); 
       }); 

     function minZoom(minZoom){ 
       if (map.getZoom()<minZoom) 
       {map.setZoom(minZoom);} 
      };  

     function limitBound(bound) 
     { 
      if (bound.getNorthEast().lat() > map.getBounds().getNorthEast().lat() 
       && bound.getNorthEast().lng() > map.getBounds().getNorthEast().lng() 
       && bound.getSouthWest().lat() < map.getBounds().getSouthWest().lat() 
       && bound.getSouthWest().lng() < map.getBounds().getSouthWest().lng()) 
       { 
        lastCenter=map.getCenter(); 
        $('#divText').text(lastCenter.toString()); 
        } 
       if (bound.contains(map.getCenter())) 
       { 
        map.setCenter(lastCenter); 
        } 
      } 
0

@sairafi y @devin

gracias por tanto sus respuestas. Pude no hacer que esto funcione en Chrome/Windows 7 porque compruebe .comtains() comprobado tanto verdadero como falso tan pronto como llegue al límite.

Así que cambió el setCenter() en la parte inferior de panTo()

El segundo problema era que si establece límites en la carga inicial, usted tiene que utilizar el google.maps.event.addListenerOnce (mapa, 'inactivo' ...) evento de lo contrario, sigue restableciendo los límites del mapa actualmente visible.

Finalmente utilizo el evento de arrastre para los centros de seguimiento, por alguna razón que funcionó mejor.

El código resultante es la siguiente:

google.maps.event.addListenerOnce(map,'idle',function() { 
     allowedBounds = map.getBounds(); 
    }); 
    google.maps.event.addListener(map,'drag',function() { 
     checkBounds(); 
    }); 
    function checkBounds() {  
     if(! allowedBounds.contains(map.getCenter())) 
     { 
      var C = map.getCenter(); 
      var X = C.lng(); 
      var Y = C.lat(); 
      var AmaxX = allowedBounds.getNorthEast().lng(); 
      var AmaxY = allowedBounds.getNorthEast().lat(); 
      var AminX = allowedBounds.getSouthWest().lng(); 
      var AminY = allowedBounds.getSouthWest().lat(); 
      if (X < AminX) {X = AminX;} 
      if (X > AmaxX) {X = AmaxX;} 
      if (Y < AminY) {Y = AminY;} 
      if (Y > AmaxY) {Y = AmaxY;} 
      map.panTo(new google.maps.LatLng(Y,X)); 
     } 
    } 
6

También podría ser necesario considerar envolver coordenadas, la distorsión de la curva, y centerizing a las dimensiones de la envolvente si el mapa cambia el tamaño o el zoom in/out. Esto es especialmente necesario si sus límites ocupan un gran porcentaje del mapa completo (por ejemplo, como un continente).

Uno de los problemas con checkBounds(), sin embargo, es que no toma en cuenta que la latitud valores cercanos al norte/polos sur, que tienen la distorsión no lineal que hacen que la limitación de los límites de precisión-(I usa multiplicadores de números mágicos aproximados que no funcionarán en todas las situaciones). A la derecha, primero debes convertir los límites a las coordenadas del mundo 2d lineales para ver qué tan lejos están de los límites en términos de coordenadas mundiales, que mapear el punto central real del objetivo en coordenadas mundiales con la posición de latitud real del objetivo.Para los valores de longitud, esto no parece ser un problema y el enfoque de recorte lineal parece lo suficientemente preciso, el problema principal es el ajuste de las coordenadas de longitud que se contabiliza (algo) en el siguiente código.

// Persitant variables 
var allowedBounds; // assign something here 
var lastValidCenter; // initialize this using map.getCenter() 

function checkBounds() { // when bounds changes due to resizing or zooming in/out 

    var currentBounds = map.getBounds(); 
    if (currentBounds == null) return; 

     var allowed_ne_lng = allowedBounds.getNorthEast().lng(); 
     var allowed_ne_lat = allowedBounds.getNorthEast().lat(); 
     var allowed_sw_lng = allowedBounds.getSouthWest().lng(); 
     var allowed_sw_lat = allowedBounds.getSouthWest().lat(); 

    var wrap; 
    var cc = map.getCenter(); 
    var centerH = false; 
    var centerV = false; 

    // Check horizontal wraps and offsets 
    if (currentBounds.toSpan().lng() > allowedBounds.toSpan().lng()) { 
     centerH = true; 
    } 
    else { // test positive and negative wrap respectively 
     wrap = currentBounds.getNorthEast().lng() < cc.lng(); 
     var current_ne_lng = !wrap ? currentBounds.getNorthEast().lng() : allowed_ne_lng +(currentBounds.getNorthEast().lng() + 180) + (180 - allowed_ne_lng); 
     wrap = currentBounds.getSouthWest().lng() > cc.lng(); 
     var current_sw_lng = !wrap ? currentBounds.getSouthWest().lng() : allowed_sw_lng - (180-currentBounds.getSouthWest().lng()) - (allowed_sw_lng+180); 
    } 


    // Check vertical wraps and offsets 
    if (currentBounds.toSpan().lat() > allowedBounds.toSpan().lat()) { 
     centerV = true; 
    } 
    else { // test positive and negative wrap respectively 
    wrap = currentBounds.getNorthEast().lat() < cc.lat(); if (wrap) { alert("WRAp detected top") } // else alert("no wrap:"+currentBounds); wrap = false; 
     var current_ne_lat = !wrap ? currentBounds.getNorthEast().lat() : allowed_ne_lat + (currentBounds.getNorthEast().lat() +90) + (90 - allowed_ne_lat); 
     wrap = currentBounds.getSouthWest().lat() > cc.lat(); if (wrap) { alert("WRAp detected btm") } //alert("no wrap:"+currentBounds); 
     var current_sw_lat = !wrap ? currentBounds.getSouthWest().lat() : allowed_sw_lat - (90-currentBounds.getSouthWest().lat()) - (allowed_sw_lat+90); 
    } 


     // Finalise positions 
     var centerX = cc.lng(); 
     var centerY = cc.lat(); 
    if (!centerH) { 
     if (current_ne_lng > allowed_ne_lng) centerX -= current_ne_lng-allowed_ne_lng; 
     if (current_sw_lng < allowed_sw_lng) centerX += allowed_sw_lng-current_sw_lng; 
    } 
    else { 
     centerX = allowedBounds.getCenter().lng(); 
    } 

    if (!centerV) { 
     if (current_ne_lat > allowed_ne_lat) { 
      centerY -= (current_ne_lat-allowed_ne_lat) * 3; // approximation magic numbeer. Adjust as u see fit, or use a more accruate pixel measurement. 
     } 
     if (current_sw_lat < allowed_sw_lat) { 
      centerY += (allowed_sw_lat-current_sw_lat)*2.8; // approximation magic number 
     } 
    } 
    else { 
     centerY = allowedBounds.getCenter().lat(); 
    } 
    map.setCenter(lastValidCenter = new google.maps.LatLng(centerY,centerX)); 
} 



function limitBound(bound) // Occurs during dragging, pass allowedBounds to this function in most cases. Requires persistant 'lastValidCenter=map.getCenter()' var reference. 
    { 
     var mapBounds = map.getBounds(); 

     if ( mapBounds.getNorthEast().lng() >= mapBounds.getSouthWest().lng() && mapBounds.getNorthEast().lat() >= mapBounds.getSouthWest().lat() // ensure no left/right, top/bottom wrapping 
      && bound.getNorthEast().lat() > mapBounds.getNorthEast().lat() // top 
      && bound.getNorthEast().lng() > mapBounds.getNorthEast().lng() // right 
      && bound.getSouthWest().lat() < mapBounds.getSouthWest().lat() // bottom 
      && bound.getSouthWest().lng() < mapBounds.getSouthWest().lng()) // left 
      { 
       lastValidCenter=map.getCenter(); // valid case, set up new valid center location 
      } 

     // if (bound.contains(map.getCenter())) 
     // { 
       map.panTo(lastValidCenter); 
      // } 

     } 



// Google map listeners 

google.maps.event.addListener(map, 'zoom_changed', function() { 
    //var zoom = map.getZoom(); 
    checkBounds(); 
}); 

google.maps.event.addListener(map, "bounds_changed", function() { 

    checkBounds(); 
}); 

google.maps.event.addListener(map, 'center_changed', function() { 
     limitBound(allowedBounds); 
}); 

p.s Para checkBounds(), para obtener la coordenada mundo 2d adecuada desde el centro del mapa, teniendo en cuenta los valores de 2 LAT/LNG, utilice map.getProjection(). FromLatLngToPoint(). Compara los 2 puntos, encuentra la diferencia lineal entre ellos y asigna la diferencia en las coordenadas del mundo a lat/lng usando map.getProjection(). FromPointToLatLng(). Esto le proporcionará correcciones de clip precisas en unidades lat/lng.

Cuestiones relacionadas