2010-09-29 4 views
82

можно ли ограничить карту Google v3 определенной областью? Я хочу разрешить отображение только некоторой области (например, страны) и запретить пользователю перемещаться в другом месте. Также я хочу ограничить уровень масштабирования - например, только между уровнями 6 и 9. И я хочу использовать все типы базовой карты.Google Maps v3 - ограничить видимую область и уровень масштабирования

Есть ли способ достичь этого?

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

Спасибо за любую помощь

ответ

112

Вы можете слушать dragend события, а если карта перетаскивать за пределы допустимых границ, переместить его обратно внутрь. Вы можете определить свои разрешенные границы в объекте LatLngBounds, а затем использовать метод , чтобы проверить, находится ли новый центр 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 API v3 Example: Force stop map dragging

+2

Решение не выглядит чистым.Почему 'if (x maxX) x = maxX;' не исключают друг друга? Почему вы центрируете холст на координатах minX/maxX и maxX/maxY, хотя они не являются координатами центра? –

+1

Вместо события 'dragend' вы можете использовать' draggable: false' на экземпляре карты ([рабочий пример] (http://jsfiddle.net/32pc6f5v/)) – machineaddict

+0

Это не очень хорошая методика использования события «zoom_changed» для ограничить пользователя. Поскольку первый раз он всегда выходит за пределы минимального уровня, а затем используя ваш код, вы снова устанавливаете мини-зум, который будет отображаться на экране. –

164

Лучший способ ограничить уровень масштабирования может быть использование minZoom/maxZoom варианты, а не реагировать на события?

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

Или параметры могут быть заданы во время инициализации карты, например:

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

См: Google Maps JavaScript API V3 Reference

+2

Теперь это, безусловно, лучший способ ограничить уровень масштабирования. Когда я писал сообщение, функции в Maps API v3 не было. К счастью, они продолжают совершенствовать API. – Tomik

+2

Это отлично работает, это должен быть лучший ответ для увеличения. – paullb

+3

Это должно быть отмечено как ответ для тех, кто смотрит только на выбранный ответ. – ErJab

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

Почему вы добавляете 'this.googleMap' вместо' map' для второго прослушивателя? Также не следует 'dragStart' быть' dragStartCenter'? Наконец, что такое 'mapBounds'? – hobbes3

+2

Несомненно, все, что делает, это то, что пользователь перетаскивает далеко вперед в одно перемещение? Они все еще могут сделать много перетаскиваний и оказаться где угодно, нет? – James

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

Принятый алгоритм Даниэля Вассалло не работает должным образом для меня. Здесь есть несколько принципиальных отличий. –

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

Надеюсь, это поможет кому-то.

-4

Это может быть полезно.

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

Уровень масштабирования может быть настроен в соответствии с требованием.

+0

Это не касается первоначального вопроса об ограничении уровня масштабирования до диапазона ', например. только между уровнями 6 и 9', он устанавливает уровень масштабирования * по умолчанию * и удаляет пользовательский интерфейс по умолчанию (т. е. '+'/'-'), который немного перебор. – Alastair

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

}); 
6

Чтобы ограничить масштаб на v.3 +. в настройках вашей карты добавьте уровень масштабирования по умолчанию и minZoom или maxZoom (или оба, если необходимо). Уровни масштабирования от 0 до 19. Если требуется ограничение, вы должны объявить уровень глухота затухания. все чувствительны к регистру!

function initialize() { 
    var mapOptions = { 
     maxZoom:17, 
     minZoom:15, 
     zoom:15, 
     .... 
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)); 
     } 
    }); 
2
myOptions = { 
     center: myLatlng, 
     minZoom: 6, 
     maxZoom: 9, 
     styles: customStyles, 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 
+0

Это не отвечает на вопрос. –

0

В среднем 2016 году, нет никакого официального способа ограничить видимую область. Однако большинство специальных решений для ограничения границ имеют недостаток, поскольку, поскольку они не ограничивают границы точно, чтобы соответствовать представлению карты, они ограничивают это только в том случае, если центр карты выходит за пределы указанных границ. Если вы хотите, чтобы ограничить рамки для наложения изображения, как я, это может привести к поведению, как Показанные ниже, где карта нижележащей видна при нашем изображении наложения:

enter image description here

Чтобы решить эту проблему, у меня есть создал library, который успешно ограничивает границы, поэтому вы не можете вырезать из наложения.

Однако, как и другие существующие решения, он имеет «вибрационную» проблему. Когда пользователь набирает карту достаточно агрессивно, после отпускания левой кнопки мыши карта по-прежнему продолжает панорамирование сама по себе, постепенно замедляя ее. Я всегда возвращаю карту обратно в границы, но это приводит к вибрации. Этот эффект панорамирования не может быть остановлен никакими средствами, предоставляемыми Js API на данный момент. Похоже, что пока 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){ 
 
\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>

Библиотека также может автоматически рассчитать минимальное ограничение масштаба. Затем он ограничивает уровень масштабирования, используя атрибут карты minZoom.

Надеюсь, это поможет кому-то, кто хочет решения, которые полностью уважают данные границы и не хотят разрешать панорамирование из них.

Смежные вопросы