Google Maps v3 - обмежте зону видимості та масштабування


97

чи можна обмежити карту Google v3 певним районом? Я хочу дозволити показ лише деякої області (наприклад, країни) і заборонити користувачеві ковзати в іншому місці. Також я хочу обмежити рівень масштабування - наприклад, лише між рівнями 6 та 9. І я хочу використовувати всі базові типи карт.

Чи є спосіб досягти цього?

Я мав частковий успіх у обмеженні рівня збільшення за допомогою StyledMap, але мені вдалося лише обмежити ROADMAP, я не зміг таким чином обмежити масштабування на інших основних типах.

Дякуємо за будь-яку допомогу

Відповіді:


119

Ви можете прослухати dragendподію, і якщо карта перетягується поза дозволеними межами, перемістіть її назад всередину. Ви можете визначити дозволені межі в LatLngBoundsоб'єкті, а потім скористатися contains()методом, щоб перевірити, чи знаходиться новий lat / lng центр в межах.

Ви також можете обмежити рівень збільшення дуже легко.

Розглянемо наступний приклад: 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>

Знімок екрана з наведеного прикладу. У цьому випадку користувач не зможе перетягнути на південь чи на схід:

Приклад Google Maps JavaScript v3 Приклад: Примусово зупинити перетягування карти


2
Рішення не виглядає чисто. Чому if (x < minX) x = minX;і if (x > maxX) x = maxX;не виключати один одного? Чому ви зосереджуєте полотно на координатах minX / maxX та maxX / maxY, хоча вони не є координатами центру?
Олександр Паламарчук

1
Замість dragendподії, яку ви можете використовувати draggable: falseна екземплярі карти ( робочий приклад )
machineaddict

Це не дуже хороша методика використання події "zoom_changed" для обмеження користувача. Оскільки перший раз він завжди виходить за мінімальний рівень, а потім використовуючи свій код, ви знову встановлюєте мінімальне збільшення, яке замикатиме екран.
Житендра Панчолі

перевірити zillow.com/homes/for_sale/days_sort/… Вони зробили це правильно, не знаю як.
Jitendra Pancholi

1
Це прекрасно працювало для мене, якщо я замінився на center_changedподію dragend.
Йоган Б

182

Кращим способом обмежити рівень збільшення може бути використання minZoom/ maxZoomпараметрів, а не реагування на події?

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

Або параметри можуть бути визначені під час ініціалізації карти, наприклад:

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

Дивіться: Довідник API API Google Maps V3


3
Тепер це, безумовно, найкращий спосіб обмежити рівень збільшення. Коли я писав публікацію, функція не була присутня в API API v3. На щастя, вони постійно вдосконалюють API.
Томік

2
Це прекрасно працює, це має бути найкращою відповіддю для збільшення.
paullb

3
Це слід позначити як відповідь для тих, хто дивиться лише на обрану відповідь.
ErJab

9
встановлення рівня збільшення не впливає на панорамування.
simpatico

1
Однозначно найкращий шлях
Крісріч

16

Гарні новини. Починаючи з версії 3.35 API JavaScript Maps, яка була запущена 14 лютого 2019 року, ви можете використовувати новуrestriction опцією, щоб обмежити вікно перегляду карти.

Відповідно до документації

Інтерфейс MapRestriction

Обмеження, яке можна застосувати до Карти. Вікно перегляду карти не перевищить цих обмежень.

джерело: https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction

Отже, тепер ви просто додаєте параметр обмеження під час ініціалізації карти і це. Подивіться наступний приклад, який обмежує вікно перегляду до Швейцарії

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>

Я сподіваюся, що це допомагає!


Посилання не працює. Ось нові теми на цю тему: ПРИКЛАД: developers-dot-devsite-v2-prod.appspot.com/maps/documentation/… DOCS: developers-dot-devsite-v2-prod.appspot.com/maps/documentation/ …
Адам

1
Фіксована посилання на документацію.
xomena

Дякую, цей код спрацював. Тобто, якщо ви обмежите масштабування лише на 1 рівень, можливий за допомогою minZoom та maxZoom. Здається, що вам потрібно встановити різні південь, захід, північ, схід для кожного рівня збільшення, якщо це працюватиме за призначенням. Було б чудово встановити різні налаштування обмеження для кожного рівня збільшення. Я пішов на максимум зменшеного рівня і визначив координати звідти, таким чином, дозволяючи панорамировать вихід із меж, якщо збільшити масштаб, а потім перемістити панораму.
Кім Штайнгауг

6

Для обмеження масштабування на v.3 +. у налаштуваннях карти додайте рівень масштабування за замовчуванням, а рівень zZ minZoom або maxZoom (або обидва, якщо потрібно) рівні масштабування становлять від 0 до 19. Ви повинні оголосити глухий рівень масштабування, якщо потрібно обмеження. всі чутливі до регістру!

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

3

Набагато кращий спосіб обмежити діапазон ... використовував містить логіку зверху плаката.

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

Чому ви додаєте this.googleMapзамість mapдругого слухача? Також не повинно dragStartбути dragStartCenter? Нарешті, що таке mapBounds?
hobbes3

2
Безумовно, все, що робить, це зупинити користувача затягуванням далеко в один рух тягнення? Вони все ще могли зробити безліч маленьких волочинок і закінчитись де завгодно, ні?
Джеймс

1

Це можна використовувати для перецентрування карти на певне місце. Що саме мені було потрібно.

    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
Це не відповідає на запитання.
Кіт Сунде

0

Ось мій варіант вирішення проблеми обмеження видимої області.

        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є об’єктом new google.maps.LatLngBounds()типу. self.gmapзберігає об’єкт Google Map ( new google.maps.Map()).

Це справді працює, але не забудьте врахувати геморой з перетином 0-го меридіану та паралелей, якщо ваші межі їх охоплюють.


Прийнятий алгоритм Даніеля Вассалло не працює належним чином для мене. Тут є кілька принципових відмінностей.
Олександр Паламарчук

0

З якоїсь причини

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

не працював для мене (можливо, питання південної півкулі). Мені довелося змінити це на:

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

Сподіваюся, це комусь допоможе.


0

Одне рішення є таким, якби ви знали конкретний lat / lng.

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

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

});

Якщо у вас немає конкретного lat / lng

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

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

});

або

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

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

});

0

Станом на середину 2016 року офіційного способу обмеження видимої площі немає. У більшості спеціальних рішень для обмеження меж є недолік, оскільки вони не обмежують межі точно так, щоб вони відповідали виду карти, вони обмежують її лише в тому випадку, якщо центр карти знаходиться поза вказаними межами. Якщо ви хочете обмежити межі накладеного зображення, як я, це може призвести до поведінки, як показано нижче, де карта підкладеного зображення видно під накладкою нашого зображення:

введіть тут опис зображення

Щоб вирішити цю проблему, я створив бібліотеку , яка успішно обмежує межі, тому ви не можете вийти з накладки.

Однак, як і інші існуючі рішення, воно має "вібруюче" питання. Коли користувач достатньо агресивно натискає на карту, після того, як вони відпустять ліву кнопку миші, карта все ще продовжує панорамитися сама по собі, поступово сповільнюючись. Я завжди повертаю карту назад до меж, але це призводить до певної вібрації. Цей ефект панорамування не може бути зупинений будь-якими засобами, наданими API Js на даний момент. Здається, що поки Google не додасть підтримку для чогось типу map.stopPanningAnimation (), ми не зможемо створити безперебійний досвід.

На прикладі використання згаданої бібліотеки я міг отримати найгладший досвід із суворими межами:

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>

Бібліотека також може автоматично обчислити мінімальне обмеження масштабу. Потім це обмежує рівень збільшення за допомогоюminZoom атрибута карти.

Сподіваємось, це допомагає тому, хто хоче знайти рішення, яке повністю дотримується заданих меж і не хоче дозволити панірувати їх.


-4

Це може бути корисним.

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

Рівень масштабування може бути налаштований відповідно до вимоги.


Це не стосується оригінального питання щодо обмеження рівня масштабування діапазоном e.g. only between levels 6 and 9, він встановлює рівень масштабування за замовчуванням і видаляє інтерфейс за замовчуванням (тобто +/ -), який трохи перевищує.
Аластер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.