Google Maps API v3: можно ли установить Zoom после fitBounds? - PullRequest
196 голосов
/ 13 марта 2010

У меня есть набор точек, которые я хочу нанести на встроенную карту Google (API v3). Я бы хотел, чтобы границы вмещали все точки, если уровень масштабирования не слишком низкий (то есть слишком сильно уменьшен). Мой подход был такой:

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

gmap.fitBounds(bounds); 
gmap.setZoom( Math.max(6, gmap.getZoom()) );

Это не работает. Последняя строка "gmap.setZoom ()" не изменяет уровень масштабирования карты, если вызывается непосредственно после fitBounds.

Есть ли способ получить уровень масштабирования границ, не применяя его к карте? Другие идеи, чтобы решить эту проблему?

Ответы [ 23 ]

325 голосов
/ 31 октября 2010

Редактировать : См. Комментарий Мэтта Даймонда ниже.

Понял! Попробуйте это:

map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() { 
  if (map.getZoom() > 16) map.setZoom(16); 
  google.maps.event.removeListener(listener); 
});

Изменить в соответствии с вашими потребностями.

66 голосов
/ 16 июля 2010

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

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

Решением было использование fitBounds, когда было много точек, и setCenter + setZoom, когда была только одна точка.

if (pointCount > 1) {
  map.fitBounds(mapBounds);
}
else if (pointCount == 1) {
  map.setCenter(mapBounds.getCenter());
  map.setZoom(14);
}
43 голосов
/ 02 февраля 2011

Я заходил на эту страницу несколько раз, чтобы получить ответ, и хотя все существующие ответы были очень полезными, они точно не решили мою проблему.

google.maps.event.addListenerOnce(googleMap, 'zoom_changed', function() {
    var oldZoom = googleMap.getZoom();
    googleMap.setZoom(oldZoom - 1); //Or whatever
});

По сути, я обнаружил, что событие zoom_changed предотвращает «пропуск» пользовательского интерфейса карты, что произошло, когда я ждал события «idle».

Надеюсь, это кому-нибудь поможет!

11 голосов
/ 24 марта 2014

Я только что исправил это, предварительно установив maxZoom, а затем удалив. Например:

map.setOptions({ maxZoom: 15 });
map.fitBounds(bounds);
map.setOptions({ maxZoom: null });
4 голосов
/ 22 июля 2010

Если я не ошибаюсь, я предполагаю, что вы хотите, чтобы все ваши точки были видны на карте с максимально возможным уровнем масштабирования. Я добился этого, установив уровень масштабирования карты на 16 (не уверен, что это максимально возможный уровень масштабирования на V3).

var map = new google.maps.Map(document.getElementById('map_canvas'), {
  zoom: 16,
  center: marker_point,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

Затем, после этого, я сделал вещи с ограничениями:

var bounds = new google.maps.LatLngBounds();

// You can have a loop here of all you marker points
// Begin loop
bounds.extend(marker_point);
// End loop

map.fitBounds(bounds);

Результат: Успех!

3 голосов
/ 25 мая 2010

Я использую:

gmap.setZoom(24); //this looks a high enough zoom value
gmap.fitBounds(bounds); //now the fitBounds should make the zoom value only less

При этом будет использоваться меньшее из 24 и необходимый уровень масштабирования в соответствии с вашим кодом, однако в любом случае он, вероятно, изменит масштаб и не будет заботиться о том, насколько вы уменьшили масштаб.

2 голосов
/ 29 июня 2012

У меня была такая же проблема, и я смог решить ее, используя следующий код. Это событие слушателя (google.maps.addListenerOnce()) будет запущено только один раз, сразу после выполнения map.fitBounds(). Таким образом, нет необходимости

  1. Отслеживание и удаление слушателя вручную или
  2. Подождите, пока карта не станет idle.

Первоначально устанавливает соответствующий уровень масштабирования и позволяет пользователю увеличивать и уменьшать масштаб после начального уровня масштабирования, поскольку срок действия прослушивателя событий истек. Например, если был вызван только google.maps.addListener(), пользователь никогда не сможет увеличить масштаб до указанного уровня масштабирования (в данном случае 4). Поскольку мы внедрили google.maps.addListenerOnce(), пользователь сможет изменять масштаб до любого уровня, который он выберет.

map.fitBounds(bounds);

var zoom_level_for_one_marker = 4;

google.maps.event.addListenerOnce(map, 'bounds_changed', function(event){
   if (this.getZoom() >= zoom_level_for_one_marker){  
       this.setZoom(zoom_level_for_one_marker) 
   }
});
2 голосов
/ 20 мая 2017

Я видел много неправильных или слишком сложных решений, поэтому решил опубликовать рабочее, элегантное решение .

Причина, по которой setZoom() не работает должным образом, заключается в том, что fitBounds() является асинхронным, поэтому он не дает гарантии, что он немедленно обновит масштаб, но ваш вызов setZoom() зависит от этого.

То, что вы могли бы рассмотреть, это установить параметр карты minZoom перед вызовом fitBounds() и затем очистить его после его завершения (чтобы пользователи могли по-прежнему уменьшать масштаб вручную, если захотят):

var bounds = new google.maps.LatLngBounds();
// ... (extend bounds with all points you want to fit)

// Ensure the map does not get too zoomed out when fitting the bounds.
gmap.setOptions({minZoom: 6});
// Clear the minZoom only after the map fits the bounds (note that
// fitBounds() is asynchronous). The 'idle' event fires when the map
// becomes idle after panning or zooming.
google.maps.event.addListenerOnce(gmap, 'idle', function() {
  gmap.setOptions({minZoom: null});
});

gmap.fitBounds(bounds);

Кроме того, если вы также хотите ограничить максимальное увеличение, вы можете применить тот же трюк со свойством maxZoom.

См. Документы MapOptions .

.
2 голосов
/ 23 декабря 2015

Пожалуйста, попробуйте это:

map.fitBounds(bounds);

// CHANGE ZOOM LEVEL AFTER FITBOUNDS
zoomChangeBoundsListener = google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
  if (this.getZoom()){
    this.setZoom(15);
  }
});
setTimeout(function(){
  google.maps.event.removeListener(zoomChangeBoundsListener)
}, 2000);
2 голосов
/ 02 апреля 2013

Я нашел решение, которое выполняет проверку перед вызовом fitBounds, чтобы вы не увеличивали и не уменьшали внезапно

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

var minLatSpan = 0.001;
if (bounds.toSpan().lat() > minLatSpan) {
    gmap.fitBounds(bounds); 
} else {
    gmap.setCenter(bounds.getCenter());
    gmap.setZoom(16);
}

Вам придется немного поиграться с переменной minLatSpan, чтобы получить ее там, где вы хотите. Он будет варьироваться в зависимости от уровня масштабирования и размеров холста карты.

Вы также можете использовать долготу вместо широты

...