Mapy Google v3 - ogranicz widoczny obszar i poziom powiększenia

97

czy można ograniczyć mapę Google v3 do określonego obszaru? Chcę zezwolić na wyświetlanie tylko niektórych obszarów (np. Kraju) i zabronić użytkownikowi przesuwania się w innym miejscu. Chcę również ograniczyć poziom powiększenia - np. Tylko między poziomami 6 i 9. Chcę używać wszystkich podstawowych typów map.

Czy jest jakiś sposób, aby to osiągnąć?

Odniosłem częściowy sukces z ograniczeniem poziomu powiększenia za pomocą StyledMap, ale udało mi się tylko z ograniczeniem ROADMAP, nie byłem w stanie ograniczyć powiększenia w ten sposób do innych podstawowych typów.

Dzięki za wszelką pomoc

Tomik
źródło

Odpowiedzi:

119

Możesz posłuchać dragendzdarzenia, a jeśli mapa zostanie przeciągnięta poza dozwolone granice, przenieś ją z powrotem do środka. Możesz zdefiniować dozwolone granice w LatLngBoundsobiekcie, a następnie użyć contains()metody, aby sprawdzić, czy nowy środek szerokości / długości geograficznej znajduje się w tych granicach.

Możesz także bardzo łatwo ograniczyć poziom powiększenia.

Rozważmy następujący przykład: 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>

Zrzut ekranu z powyższego przykładu. W takim przypadku użytkownik nie będzie mógł przeciągnąć dalej na południe ani na daleki wschód:

Google Maps JavaScript API v3 Przykład: wymuś zatrzymanie przeciągania mapy

Daniel Vassallo
źródło
2
Decyzja nie wygląda na trafną. Dlaczego if (x < minX) x = minX;i if (x > maxX) x = maxX;nie wykluczajcie się wzajemnie? Dlaczego wyśrodkowujesz płótno na współrzędnych minX / maxX i maxX / maxY, chociaż nie są to współrzędne środka?
Alexander Palamarchuk,
1
Zamiast dragendzdarzenia można by użyć draggable: falsena mapie ( przykład roboczy )
machineaddict
To nie jest dobra technika używania zdarzenia „zoom_changed” do ograniczania użytkownika. Ponieważ za pierwszym razem zawsze wykracza to poza poziom minimalny, a następnie używając twojego kodu, ponownie ustawiasz minimalny zoom, który będzie migotał na ekranie.
Jitendra Pancholi,
sprawdź zillow.com/homes/for_sale/days_sort/… Zrobili to w prawidłowy sposób, nie wiem jak.
Jitendra Pancholi,
1
To zadziałało idealnie, gdybym center_changedzamiast tego zmienił wydarzenie dragend.
Johan B
182

Lepszym sposobem ograniczenia poziomu powiększenia może być użycie opcji minZoom/ maxZoomzamiast reagowania na zdarzenia?

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

Lub opcje można określić podczas inicjalizacji mapy, np .:

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

Zobacz: Dokumentacja interfejsu API JavaScript w Mapach Google V3

ChrisV
źródło
3
To z pewnością najlepszy sposób na ograniczenie poziomu powiększenia. Kiedy pisałem ten post, funkcja nie była obecna w Maps API v3. Na szczęście ciągle ulepszają API.
Tomik
2
To działa idealnie, to powinna być najlepsza odpowiedź na powiększenie.
paullb
3
Powinno to być oznaczone jako odpowiedź dla tych, którzy patrzą tylko na wybraną odpowiedź.
ErJab
9
ustawienie poziomu powiększenia nie ma wpływu na panoramowanie.
simpatico
1
Zdecydowanie najlepszy sposób
ChrisRich
16

Dobre wieści. Począwszy od wersji 3.35 Maps JavaScript API, która została uruchomiona 14 lutego 2019 r., Możesz skorzystać z nowej restrictionopcji, aby ograniczyć obszar wyświetlania mapy.

Zgodnie z dokumentacją

Interfejs MapRestriction

Ograniczenie, które można zastosować do mapy. Widok mapy nie przekroczy tych ograniczeń.

źródło: https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction

Więc teraz po prostu dodajesz opcję ograniczenia podczas inicjalizacji mapy i to wszystko. Spójrz na poniższy przykład, który ogranicza widok do Szwajcarii

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>

Mam nadzieję, że to pomoże!

xomena
źródło
1
Naprawiono link do dokumentacji.
xomena
Dziękuję, ten kod działał. Oznacza to, że jeśli ograniczysz zoom tylko do 1 poziomu możliwego przy użyciu minZoom i maxZoom. Wygląda na to, że musisz ustawić różne poziomy południowego, zachodniego, północnego i wschodniego dla każdego poziomu powiększenia, jeśli to zadziała zgodnie z przeznaczeniem. Byłoby wspaniale mieć różne ustawienia ograniczeń dla każdego poziomu powiększenia. Poszedłem na maksymalny poziom pomniejszenia i zdefiniowałem współrzędne z tego miejsca, umożliwiając w ten sposób przesuwanie poza granice, jeśli powiększysz, a następnie przesuniesz.
Kim Steinhaug
6

Aby ograniczyć powiększenie w wersji 3+. w ustawieniach mapy dodaj domyślny poziom powiększenia i minZoom lub maxZoom (lub oba, jeśli jest to wymagane) poziomy powiększenia od 0 do 19. Musisz zadeklarować głuchy poziom powiększenia, jeśli wymagane jest ograniczenie. wszystkie rozróżniają wielkość liter!

function initialize() {
   var mapOptions = {
      maxZoom:17,
      minZoom:15,
      zoom:15,
      ....
GŁĘBOKIE SREBRO
źródło
3

Znacznie lepszy sposób na ograniczenie zakresu ... wykorzystałem logikę zawiera z powyższego plakatu.

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);
                           });
Poklepać
źródło
Dlaczego dodajesz this.googleMapzamiast mapdla drugiego słuchacza? Też nie powinno dragStartbyć dragStartCenter? Wreszcie, co jest mapBounds?
hobbes3
2
Z pewnością wszystko, co robi, to powstrzymanie użytkownika przed przeciąganiem zbyt daleko jednym ruchem przeciągania? Nadal mogliby zrobić wiele małych przeciągnięć i skończyć gdziekolwiek, nie?
James
1

Można to wykorzystać do ponownego wyśrodkowania mapy do określonej lokalizacji. Czego potrzebowałem.

    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));
        }
    });
Jonathan Busuttil
źródło
1
myOptions = {
        center: myLatlng,
        minZoom: 6,
        maxZoom: 9,
        styles: customStyles,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
Anup
źródło
1
To nie odpowiada na pytanie.
Kit Sunde,
0

Oto mój wariant rozwiązania problemu ograniczenia widocznego obszaru.

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

strictBoundsjest obiektem new google.maps.LatLngBounds()typu. self.gmapprzechowuje obiekt mapy Google ( new google.maps.Map()).

To naprawdę działa, ale nie zapomnij wziąć pod uwagę hemoroidów z przekroczeniem południków zerowych i równoleżników, jeśli Twoje granice je pokrywają.

Alexander Palamarchuk
źródło
Zaakceptowany algorytm Daniela Vassallo nie działa poprawnie dla mnie. Jest tutaj kilka zasadniczych różnic.
Alexander Palamarchuk,
0

Z jakiegoś powodu

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

nie zadziałało dla mnie (może problem półkuli południowej). Musiałem to zmienić na:

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

Mam nadzieję, że to komuś pomoże.

Mayko
źródło
0

Jedno rozwiązanie jest takie, że jeśli znasz konkretny lat / lng.

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

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

});

Jeśli nie masz konkretnych lat / lng

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

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

});

lub

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

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

});
Jaison
źródło
0

Od połowy 2016 r. Nie ma oficjalnego sposobu ograniczenia widocznego obszaru. Większość rozwiązań ad-hoc ograniczających granice ma jednak wadę, ponieważ nie ograniczają granic dokładnie tak, aby pasowały do ​​widoku mapy, ograniczają je tylko wtedy, gdy środek mapy znajduje się poza określonymi granicami. Jeśli chcesz ograniczyć granice do nakładającego się obrazu, takiego jak ja, może to spowodować zachowanie, jak pokazano poniżej, gdzie mapa podkładania jest widoczna pod naszą nakładką obrazu:

wprowadź opis obrazu tutaj

Aby rozwiązać ten problem, utworzyłem bibliotekę , która z powodzeniem ogranicza granice, więc nie można przesuwać się z nakładki.

Jednak podobnie jak inne istniejące rozwiązania ma problem z „wibracjami”. Kiedy użytkownik przesuwa mapę wystarczająco agresywnie, po zwolnieniu lewego przycisku myszy, mapa nadal się przesuwa, stopniowo zwalniając. Zawsze zwracam mapę z powrotem do granic, ale to powoduje wibracje. Tego efektu panoramowania nie można obecnie zatrzymać za pomocą żadnych środków udostępnionych przez interfejs API Js. Wygląda na to, że dopóki Google nie doda obsługi czegoś takiego jak map.stopPanningAnimation (), nie będziemy w stanie stworzyć płynnego doświadczenia.

Przykład korzystania ze wspomnianej biblioteki, najbardziej płynne doświadczenie w zakresie ścisłych ograniczeń, jakie udało mi się uzyskać:

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>

Biblioteka jest również w stanie automatycznie obliczyć minimalne ograniczenie zoomu. Następnie ogranicza poziom powiększenia za pomocąminZoom atrybutu mapy.

Miejmy nadzieję, że pomoże to komuś, kto chce rozwiązania, które w pełni szanuje podane granice i nie chce pozwolić na ich przesuwanie.

Matej P.
źródło
-4

To może być pomocne.

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

Poziom powiększenia można dostosować zgodnie z wymaganiami.

Samir Dash
źródło
Nie rozwiązuje to pierwotnego pytania o ograniczenie poziomu powiększenia do zakresu e.g. only between levels 6 and 9, ustawia domyślny poziom powiększenia i usuwa domyślny interfejs użytkownika (tj. +/ -), Który jest trochę przesadzony.
Alastair