2010-09-29 27 views
82

¿es posible limitar el mapa de Google v3 a un área determinada? Quiero permitir que se muestre solo un área determinada (por ejemplo, un país) y no permitir que el usuario se desplace en otro lugar. También quiero restringir el nivel de zoom, p. solo entre los niveles 6 y 9. Y quiero usar todos los tipos de mapas base.Google Maps v3: área visible límite y nivel de zoom

¿Hay alguna manera de lograr esto?

Tuve un éxito parcial al limitar el nivel de zoom usando StyledMap, pero tuve éxito solo con restringir ROADMAP, no pude limitar el zoom en otros tipos básicos de esta manera.

Gracias por cualquier ayuda

Respuesta

112

Puede escuchar el evento dragend, y si el mapa se arrastró fuera de los límites permitidos, desplazarlo hacia el interior. Puede definir sus límites permitidos en un objeto LatLngBounds y luego usar el método para verificar si el nuevo centro lat/lng está dentro de los límites.

También puede limitar el nivel de zoom muy fácilmente.

Consideremos el siguiente ejemplo: Fiddle Demo

<!DOCTYPE html> 
<html> 
<head> 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
    <title>Google Maps JavaScript API v3 Example: Limit Panning and Zoom</title> 
    <script type="text/javascript" 
      src="http://maps.google.com/maps/api/js?sensor=false"></script> 
</head> 
<body> 
    <div id="map" style="width: 400px; height: 300px;"></div> 

    <script type="text/javascript"> 

    // This is the minimum zoom level that we'll allow 
    var minZoomLevel = 5; 

    var map = new google.maps.Map(document.getElementById('map'), { 
     zoom: minZoomLevel, 
     center: new google.maps.LatLng(38.50, -90.50), 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    }); 

    // Bounds for North America 
    var strictBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(28.70, -127.50), 
    new google.maps.LatLng(48.85, -55.90) 
    ); 

    // Listen for the dragend event 
    google.maps.event.addListener(map, 'dragend', 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)); 
    }); 

    // Limit the zoom level 
    google.maps.event.addListener(map, 'zoom_changed', function() { 
    if (map.getZoom() < minZoomLevel) map.setZoom(minZoomLevel); 
    }); 

    </script> 
</body> 
</html> 

pantalla del ejemplo anterior. El usuario no será capaz de arrastrar más al sur o al este momento, en este caso:

Google Maps JavaScript API v3 Example: Force stop map dragging

+2

La decisión no parece clara.¿Por qué 'if (x maxX) x = maxX;' no se excluyen entre sí? ¿Por qué centras el lienzo en las coordenadas minX/maxX y maxX/maxY aunque no son coordenadas del centro? –

+1

En lugar del evento 'dragend', podría usar' draggable: false' en la instancia del mapa ([working example] (http://jsfiddle.net/32pc6f5v/)) – machineaddict

+0

Esta no es una buena técnica para usar el evento "zoom_changed" para restringir al usuario. Debido a que la primera vez siempre va más allá del nivel mínimo y luego usa tu código, estás configurando el zoom min nuevamente, lo cual hará que la pantalla parpadee. –

164

mejor manera de restringir el nivel de zoom podría ser utilizar los minZoom/maxZoom opciones en lugar de reaccionar a los eventos?

var opt = { minZoom: 6, maxZoom: 9 }; 
map.setOptions(opt); 

o las opciones pueden ser especificadas durante la inicialización del mapa, por ejemplo:

var map = new google.maps.Map(document.getElementById('map-canvas'), opt); 

Ver: Google Maps JavaScript API V3 Reference

+2

Ahora bien, esta es seguramente la mejor manera de restringir el nivel de zoom. Cuando estaba escribiendo la publicación, la función no estaba presente en Maps API v3. Afortunadamente, siguen mejorando la API. – Tomik

+2

Esto funciona perfectamente, esta debería ser la mejor respuesta para el zoom. – paullb

+3

Esto debe marcarse como la respuesta para aquellos que solo miran la respuesta elegida. – ErJab

3

Mucho mejor manera de limitar la gama ... utiliza la lógica contiene desde arriba del cartel .

var dragStartCenter; 

google.maps.event.addListener(map, 'dragstart', function(){ 
             dragStartCenter = map.getCenter(); 
             }); 

google.maps.event.addListener(this.googleMap, 'dragend', function(){ 
          if (mapBounds.contains(map.getCenter())) return; 
        map.setCenter(this.dragStart); 
          }); 
+0

¿Por qué agrega 'this.googleMap' en lugar de' map' para el segundo oyente? Además, ¿no debería 'dragStart' ser' dragStartCenter'? Por último, ¿qué es 'mapBounds'? – hobbes3

+2

Seguramente todo lo que hace es detener al usuario arrastrando hasta lejos en un movimiento de arrastre? Todavía podrían hacer muchos pequeños drags y terminar en cualquier parte, ¿no? – James

0

Aquí está mi variante para resolver el problema de la limitación del área visible.

 google.maps.event.addListener(this.map, 'idle', function() { 
      var minLat = strictBounds.getSouthWest().lat(); 
      var minLon = strictBounds.getSouthWest().lng(); 
      var maxLat = strictBounds.getNorthEast().lat(); 
      var maxLon = strictBounds.getNorthEast().lng(); 
      var cBounds = self.map.getBounds(); 
      var cMinLat = cBounds.getSouthWest().lat(); 
      var cMinLon = cBounds.getSouthWest().lng(); 
      var cMaxLat = cBounds.getNorthEast().lat(); 
      var cMaxLon = cBounds.getNorthEast().lng(); 
      var centerLat = self.map.getCenter().lat(); 
      var centerLon = self.map.getCenter().lng(); 

      if((cMaxLat - cMinLat > maxLat - minLat) || (cMaxLon - cMinLon > maxLon - minLon)) 
      { //We can't position the canvas to strict borders with a current zoom level 
       self.map.setZoomLevel(self.map.getZoomLevel()+1); 
       return; 
      } 
      if(cMinLat < minLat) 
       var newCenterLat = minLat + ((cMaxLat-cMinLat)/2); 
      else if(cMaxLat > maxLat) 
       var newCenterLat = maxLat - ((cMaxLat-cMinLat)/2); 
      else 
       var newCenterLat = centerLat; 
      if(cMinLon < minLon) 
       var newCenterLon = minLon + ((cMaxLon-cMinLon)/2); 
      else if(cMaxLon > maxLon) 
       var newCenterLon = maxLon - ((cMaxLon-cMinLon)/2); 
      else 
       var newCenterLon = centerLon; 

      if(newCenterLat != centerLat || newCenterLon != centerLon) 
       self.map.setCenter(new google.maps.LatLng(newCenterLat, newCenterLon)); 
     }); 

strictBounds Es un objeto de new google.maps.LatLngBounds() tipo. self.gmap almacena un objeto Google Map (new google.maps.Map()).

Realmente funciona, pero no se olvide de tener en cuenta las hemorroides con el cruce de los meridianos y los paralelos si los cubren.

+0

El algoritmo aceptado de Daniel Vassallo no funciona correctamente para mí. Aquí hay varias diferencias principales de esto. –

0

Por alguna razón

if (strictBounds.contains(map.getCenter())) return; 

no funcionó para mí (tal vez un tema hemisferio sur). Tuve que cambiarlo a:

function checkBounds() { 
     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 > maxX || y < minY || y > maxY) { 
      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)); 
     } 
    } 

Espero que ayude a alguien.

-4

Esto puede ser útil.

var myOptions = { 
     center: new google.maps.LatLng($lat,$lang), 
     zoom: 7, 
     disableDefaultUI: true, 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 

El nivel de Zoom se puede personalizar de acuerdo con el requisito.

+0

Esto no aborda la pregunta original sobre la restricción del nivel de zoom a un rango 'p. Ej. solo entre los niveles 6 y 9', establece el nivel de zoom * predeterminado * y elimina la IU predeterminada (es decir, '+'/'-') que es un poco exagerada. – Alastair

0

Una solución es como, si conoce el lat/lng específico.

google.maps.event.addListener(map, 'idle', function() { 

    map.setCenter(new google.maps.LatLng(latitude, longitude)); 
    map.setZoom(8); 

}); 

Si no tenemos específica lat/lng

google.maps.event.addListener(map, 'idle', function() { 

    map.setCenter(map.getCenter()); 
    map.setZoom(8); 

}); 

o

google.maps.event.addListener(map, 'idle', function() { 

    var bounds = new google.maps.LatLngBounds(); 
    map.setCenter(bounds.getCenter()); 
    map.setZoom(8); 

}); 
6

Para limitar el zoom de la versión 3 +. en la configuración del mapa agregar el nivel de zoom predeterminado y minZoom o maxZoom (o ambos si es necesario) los niveles de zoom son de 0 a 19. Debe declarar el nivel de zoom de la sordera si se requiere una limitación. todos son sensibles a las mayúsculas

function initialize() { 
    var mapOptions = { 
     maxZoom:17, 
     minZoom:15, 
     zoom:15, 
     .... 
1

Esto se puede utilizar para volver a centrar el mapa en una ubicación específica. Que es lo que necesitaba.

var MapBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(35.676263, 13.949096), 
    new google.maps.LatLng(36.204391, 14.89038)); 

    google.maps.event.addListener(GoogleMap, 'dragend', function() 
    { 
     if (MapBounds.contains(GoogleMap.getCenter())) 
     { 
      return; 
     } 
     else 
     { 
      GoogleMap.setCenter(new google.maps.LatLng(35.920242, 14.428825)); 
     } 
    }); 
2
myOptions = { 
     center: myLatlng, 
     minZoom: 6, 
     maxZoom: 9, 
     styles: customStyles, 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 
+0

Esto no responde la pregunta. –

0

A partir de mediados 2016, no hay manera oficial a restringir el área visible. La mayoría de las soluciones ad-hoc para restringir los límites tienen una falla, porque no restringen los límites exactamente para ajustarse a la vista del mapa, solo lo restringen si el centro del mapa está fuera de los límites especificados. Si desea restringir los límites a la imagen superpuesta como yo, esto puede dar lugar a un comportamiento como se ilustra a continuación, donde el mapa subyacente es visible bajo nuestra superposición de imágenes:

enter image description here

Para hacer frente a este problema, no tengo creó un library, que restringe con éxito los límites para que no pueda salir de la superposición.

Sin embargo, como otras soluciones existentes, tiene un problema de "vibración". Cuando el usuario muestra el mapa con la fuerza suficiente, después de que suelta el botón izquierdo del mouse, el mapa continúa avanzando por su cuenta, desacelerándose gradualmente. Siempre devuelvo el mapa a los límites, pero eso da como resultado un tipo de vibración. Este efecto de panoramización no puede detenerse con ningún medio provisto por la API Js en este momento. Parece que hasta que google agregue soporte para algo como map.stopPanningAnimation() no podremos crear una experiencia fluida.

Ejemplo usando la biblioteca se ha mencionado, la experiencia más suave estrictos límites pude conseguir:

function initialise(){ 
 
    
 
    var myOptions = { 
 
    zoom: 5, 
 
    center: new google.maps.LatLng(0,0), 
 
    mapTypeId: google.maps.MapTypeId.ROADMAP, 
 
    }; 
 
    var map = new google.maps.Map(document.getElementById('map'), myOptions); 
 
    
 
    addStrictBoundsImage(map); 
 
} 
 

 
function addStrictBoundsImage(map){ 
 
\t var bounds = new google.maps.LatLngBounds(
 
\t \t new google.maps.LatLng(62.281819, -150.287132), 
 
\t \t new google.maps.LatLng(62.400471, -150.005608)); 
 

 
\t var image_src = 'https://developers.google.com/maps/documentation/' + 
 
\t \t 'javascript/examples/full/images/talkeetna.png'; 
 

 
\t var strict_bounds_image = new StrictBoundsImage(bounds, image_src, map); 
 
}
<script type="text/javascript" src="http://www.google.com/jsapi"></script> 
 
     <script type="text/javascript"> 
 
     google.load("maps", "3",{other_params:"sensor=false"}); 
 
     </script> 
 
<body style="margin:0px; padding:0px;" onload="initialise()"> 
 
\t <div id="map" style="height:400px; width:500px;"></div> 
 
    <script type="text/javascript"src="https://raw.githubusercontent.com/matej-pavla/StrictBoundsImage/master/StrictBoundsImage.js"></script> 
 
</body>

La biblioteca también es capaz de calcular la restricción mínima de zoom automáticamente. A continuación, restringe el nivel de zoom utilizando el atributo del mapa minZoom.

Esperamos que esto ayude a alguien que quiere una solución que respete completamente los límites dados y no quiera permitir el barrido de ellos.

Cuestiones relacionadas