Google Maps v3: limita l'area visualizzabile e il livello di zoom


97

è possibile limitare la mappa di Google v3 a una determinata area? Desidero consentire la visualizzazione solo di alcune aree (ad esempio un paese) e impedire all'utente di scorrere altrove. Inoltre, voglio limitare il livello di zoom, ad esempio solo tra i livelli 6 e 9. E voglio usare tutti i tipi di mappa di base.

C'è un modo per ottenere questo risultato?

Ho avuto un successo parziale con la limitazione del livello di zoom utilizzando StyledMap, ma sono riuscito solo con la limitazione della ROADMAP, non sono stato in grado di limitare lo zoom su altri tipi di base in questo modo.

Grazie per qualsiasi aiuto

Risposte:


119

È possibile ascoltare l' dragendevento e, se la mappa viene trascinata al di fuori dei limiti consentiti, spostarla nuovamente all'interno. È possibile definire i limiti consentiti in un LatLngBoundsoggetto e quindi utilizzare il contains()metodo per verificare se il nuovo centro latitudine / longitudine si trova entro i limiti.

Puoi anche limitare il livello di zoom molto facilmente.

Considera il seguente esempio: 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>

Screenshot dell'esempio precedente. L'utente non sarà in grado di trascinare più a sud o estremo est in questo caso:

Esempio di API JavaScript di Google Maps v3: forza l'arresto del trascinamento della mappa


2
La decisione non sembra chiara. Perché if (x < minX) x = minX;e if (x > maxX) x = maxX;non escludersi a vicenda? Perché centrate la tela sulle coordinate minX / maxX e maxX / maxY sebbene non siano coordinate del centro?
Alexander Palamarchuk

1
Invece di un dragendevento potresti usare draggable: false
sull'istanza della

Questa non è una buona tecnica per utilizzare l'evento "zoom_changed" per limitare l'utente. Perché la prima volta andrà sempre oltre il livello minimo e quindi utilizzando il codice, stai impostando di nuovo lo zoom minimo che farà girare lo schermo.
Jitendra Pancholi

controllare zillow.com/homes/for_sale/days_sort/… L' hanno fatto in modo corretto, non sono sicuro di come.
Jitendra Pancholi

1
Questo ha funzionato perfettamente per me se sono passato center_changedall'evento invece di dragend.
Johan B,

182

Un modo migliore per limitare il livello di zoom potrebbe essere quello di utilizzare le opzioni minZoom/ maxZoompiuttosto che reagire agli eventi?

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

Oppure le opzioni possono essere specificate durante l'inizializzazione della mappa, ad esempio:

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

Vedi: Google Maps JavaScript API V3 Reference


3
Questo è sicuramente il modo migliore per limitare il livello di zoom. Quando stavo scrivendo il post, la funzionalità non era presente in Maps API v3. Per fortuna, continuano a migliorare l'API.
Tomik

2
Funziona perfettamente, questa dovrebbe essere la migliore risposta per lo zoom.
paullb

3
Questa dovrebbe essere contrassegnata come risposta per coloro che guardano solo la risposta scelta.
ErJab

9
l'impostazione del livello di zoom non ha effetto sulla panoramica.
simpatico

1
Sicuramente il modo migliore per andare
ChrisRich

16

Buone notizie. A partire dalla versione 3.35 dell'API JavaScript di Maps, che è stata lanciata il 14 febbraio 2019, è possibile utilizzare una nuova restrictionopzione per limitare la visualizzazione della mappa.

Secondo la documentazione

Interfaccia MapRestriction

Una restrizione che può essere applicata alla mappa. La visualizzazione della mappa non supererà queste restrizioni.

fonte: https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction

Quindi, ora aggiungi solo un'opzione di restrizione durante l'inizializzazione di una mappa e questo. Dai un'occhiata al seguente esempio che limita il viewport alla Svizzera

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 46.818188, lng: 8.227512},
    minZoom: 7,
    maxZoom: 14,
    zoom: 7,
    restriction: {
      latLngBounds: {
        east: 10.49234,
        north: 47.808455,
        south: 45.81792,
        west: 5.95608
      },
      strictBounds: true
    },
  });
}
#map {
  height: 100%;
}
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap" async defer></script>

Spero che aiuti!



1
Corretto il collegamento alla documentazione.
xomena

Grazie, questo codice ha funzionato. Cioè, se limiti lo zoom a un solo livello possibile con minZoom e maxZoom. Sembra che sia necessario impostare diversi sud, ovest, niente, est per ogni livello di zoom se funziona come previsto. Sarebbe bello avere un'impostazione di restrizione diversa per ogni livello di zoom. Ho scelto il mio livello massimo di zoom indietro e ho definito le coordinate da lì, rendendo così possibile la panoramica fuori dai limiti se si ingrandisce e poi si esegue la panoramica.
Kim Steinhaug

6

Per limitare lo zoom su v.3 +. nelle impostazioni della mappa aggiungi il livello di zoom predefinito e i livelli di zoom minZoom o maxZoom (o entrambi se richiesti) sono compresi tra 0 e 19. Se è richiesta una limitazione, devi dichiarare il livello di zoom sordo. tutti fanno distinzione tra maiuscole e minuscole!

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

3

Un modo molto migliore per limitare l'intervallo ... utilizzato la logica contiene dal poster sopra.

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

Perché aggiungi this.googleMapinvece che mapper il secondo ascoltatore? Inoltre non dovrebbe dragStartessere dragStartCenter? Infine cos'è mapBounds?
hobbes3

2
Sicuramente tutto ciò che fa è impedire all'utente di trascinare troppo lontano con un movimento di trascinamento? Potrebbero ancora fare tanti piccoli tiri e finire ovunque, no?
James

1

Questo può essere utilizzato per ricentrare la mappa su una posizione specifica. Che è quello di cui avevo bisogno.

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

1
myOptions = {
        center: myLatlng,
        minZoom: 6,
        maxZoom: 9,
        styles: customStyles,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

1
Questo non risponde alla domanda.
Kit Sunde

0

Ecco la mia variante per risolvere il problema della limitazione dell'area visualizzabile.

        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è un oggetto di new google.maps.LatLngBounds()tipo. self.gmapmemorizza un oggetto Google Map ( new google.maps.Map()).

Funziona davvero ma non dimenticare di prendere in considerazione solo le emorroidi con attraversamento dei meridiani 0 e paralleli se i tuoi limiti le coprono.


L'algoritmo di Daniel Vassallo accettato non funziona correttamente per me. Ci sono molte differenze principali qui.
Alexander Palamarchuk

0

Per qualche ragione

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

non ha funzionato per me (forse un problema dell'emisfero meridionale). Ho dovuto cambiarlo in:

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

Spero che possa aiutare qualcuno.


0

Una soluzione è come, se conosci il lat / lng specifico.

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

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

});

Se non hai lat / lng specifici

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

});

0

A partire dalla metà del 2016 , non esiste un modo ufficiale per limitare l'area visualizzabile. La maggior parte delle soluzioni ad-hoc per limitare i limiti presenta tuttavia un difetto, poiché non limitano i limiti esattamente per adattarsi alla visualizzazione della mappa, ma solo se il centro della mappa è fuori dai limiti specificati. Se desideri limitare i limiti all'immagine sovrapposta come me, questo può comportare un comportamento come illustrato di seguito, in cui la mappa sottostante è visibile sotto la nostra sovrapposizione di immagini:

inserisci qui la descrizione dell'immagine

Per affrontare questo problema, ho creato una libreria , che limita correttamente i limiti in modo da non poter eseguire la panoramica dell'overlay.

Tuttavia, come altre soluzioni esistenti, presenta un problema di "vibrazione". Quando l'utente esegue la panoramica della mappa in modo abbastanza aggressivo, dopo aver rilasciato il pulsante sinistro del mouse, la mappa continua comunque a scorrere da sola, rallentando gradualmente. Riporto sempre la mappa ai limiti, ma ciò si traduce in una sorta di vibrazione. Questo effetto di panoramica non può essere interrotto con alcun mezzo fornito dall'API Js al momento. Sembra che fino a quando Google non aggiungerà il supporto per qualcosa come map.stopPanningAnimation () non saremo in grado di creare un'esperienza fluida.

Esempio utilizzando la libreria menzionata, l'esperienza di limiti rigorosi più fluida che sono stato in grado di ottenere:

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){
	var bounds = new google.maps.LatLngBounds(
		new google.maps.LatLng(62.281819, -150.287132),
		new google.maps.LatLng(62.400471, -150.005608));

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

	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()">
	 <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 libreria è anche in grado di calcolare automaticamente la restrizione minima dello zoom. Quindi limita il livello di zoom utilizzando minZooml'attributo della mappa.

Si spera che questo aiuti qualcuno che desidera una soluzione che rispetti pienamente i limiti dati e non vuole consentire la panoramica di essi.


-4

Questo può essere utile.

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

Il livello di Zoom può essere personalizzabile in base alle esigenze.


Questo non risolve la domanda originale sulla limitazione del livello di zoom a un intervallo e.g. only between levels 6 and 9, imposta il livello di zoom predefinito e rimuove l'interfaccia utente predefinita (ad es.+ / -) che è un po 'eccessiva.
Alastair
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.