Google Maps v3: Застосування мінімальної рівень масштабування при використанні fitBounds


79

Я малюю серію маркерів на карті (використовуючи v3 карти api).

У версії 2 я мав такий код:

  bounds = new GLatLngBounds();

  ... loop thru and put markers on map ...
  bounds.extend(point);
  ... end looping

  map.setCenter(bounds.getCenter());
  var level = map.getBoundsZoomLevel(bounds);
  if ( level == 1 ) 
    level = 5;
  map.setZoom(level > 6 ? 6 : level);

І це чудово працює, щоб на карті завжди відображався відповідний рівень деталізації.

Я намагаюся продублювати цю функціональність у v3, але setZoom та fitBounds, здається, не співпрацюють:

... loop thru and put markers on the map
  var ll = new google.maps.LatLng(p.lat,p.lng);
  bounds.extend(ll);
... end loop

var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);
map.fitBounds(bounds);

Я пробував різні перестановки (наприклад, переміщуючи fitBounds перед setZoom), але, здається, нічого, що я роблю з setZoom, не впливає на карту. Мені чогось не вистачає? Чи є спосіб зробити це?

Відповіді:


137

Під час цього обговорення в Google Groups я виявив, що в основному, коли ви встановлюєте fitBounds, масштабування відбувається асинхронно, тому вам потрібно зафіксувати подію зміни масштабу та меж. Код в останньому дописі спрацював для мене з невеликою зміною ... оскільки він стоїть, він повністю зупиняє масштабування більше 15, тому використовував ідею з четвертого поста, щоб встановити прапор, щоб робити це лише вперше.

// Do other stuff to set up map
var map = new google.maps.Map(mapElement, myOptions);
// This is needed to set the zoom after fitbounds, 
google.maps.event.addListener(map, 'zoom_changed', function() {
    zoomChangeBoundsListener = 
        google.maps.event.addListener(map, 'bounds_changed', function(event) {
            if (this.getZoom() > 15 && this.initialZoom == true) {
                // Change max/min zoom here
                this.setZoom(15);
                this.initialZoom = false;
            }
        google.maps.event.removeListener(zoomChangeBoundsListener);
    });
});
map.initialZoom = true;
map.fitBounds(bounds);

Сподіваюся, що це допоможе,

Антоній.


4
Це хороший метод. Інший метод - перевірити поточні межі та розширити межі, тобто stackoverflow.com/questions/3334729/… . Хоча зв’язана відповідь тут лише розширює межі на дріб, ви можете використовувати той самий метод, щоб розширити межі на більшу кількість; Я виявив, що додавання 7 до всіх кутів робить хорошу роботу.
Metro Smurf

2
Я хотів би виправити свій попередній коментар. Я вважаю, що може знадобитися встановлення властивості InitialZoom. У мене були проблеми з масштабуванням в реальному масштабі IE 9 після того, як я залишив цю частину коду ... Класне рішення!
Ендрю

21
Використовуйте google.maps.event.addListenerOnce(), щоб потім не потрібно було вручну видаляти слухач.
пстадлер

5
Оскільки я дивлюся на це вже втретє, ось версія для гольфу. Дякую @pstadler. google.maps.event.addListenerOnce(map, 'bounds_changed', function() { this.setZoom(Math.min(15, this.getZoom())); });
сба

1
При використанні addLIstenerOnce ви можете просто слухати zoom_changed. Я використовую zoom_changedнезадовго до цього, map.fitBounds(bounds);і, здається, чудово працює в Chrome.
Milk Man

63

Не намагаючись, я б сказав, що ви зможете це зробити, просто маючи, fitBounds()перш ніж отримати рівень масштабування, тобто

map.fitBounds(bounds);
var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);

Якщо ви спробували це, але це не спрацювало, ви можете налаштувати свою карту за minZoomдопомогою MapOptions (api-reference) таким чином:

var map = new google.maps.Map(document.getElementById("map"), { minZoom: 6 });

Це не дозволить збільшити масштаб карти під час використання fitBounds().


приємне просте та елегантне рішення!
Falantar014,

3
Встановлення значень minZoom та maxZoom обмежує користувача в масштабуванні за межами цих значень, тому це не допомагає, якщо все, що ви хочете зробити, це встановити початкове масштабування на щось розумне (саме про це, на мою думку, говорив ОП)
Ізазаел

5
Отже, в основному саме так, як я писав у своїй відповіді?
Flygenring

@Izazael робить хороший момент, про який не йдеться у відповіді. Це чудово, якщо зупинити fitBounds()занадто масштабування, але також обмежує взаємодію користувача з кнопками масштабування на карті. Прийнята відповідь - кращий варіант, якщо ви вважаєте за краще, щоб користувач мав повний контроль.
Rich Court

1
Може не спрацювати, оскільки з новими версіями. fitBounds () працює асинхронно!
RubbelDeCatc

19

Ви також можете встановити опцію maxZoom безпосередньо перед викликом fitBounds () і після цього скинути значення:

if(!bounds.isEmpty()) {
    var originalMaxZoom = map.maxZoom;
    map.setOptions({maxZoom: 18});
    map.fitBounds(bounds);
    map.setOptions({maxZoom: originalMaxZoom});
}

Мені подобається цей варіант, оскільки він не викликає zoom_changedподії в два рази, як багато інших варіантів
Грег

Чудове рішення, коли для об’єкта max визначено опцію maxZoom.
Олексій Доманський

17

Рішення Антонія дуже приємне. Мені потрібно було лише виправити масштабування для початкового завантаження сторінки (переконавшись, що для початку ви не були занадто масштабовані), і це зробило для мене фокус:

var zoomChangeBoundsListener =
    google.maps.event.addListener(map, 'bounds_changed', function(event) {
        google.maps.event.removeListener(zoomChangeBoundsListener);
        map.setZoom( Math.min( 15, map.getZoom() ) );
    });


map.fitBounds( zoomBounds );

5
Замість видалення слухача ви можете використовувати addListenerOnce, але я використовую це рішення.
Дерек С

11

Коли ви телефонуєте map.fitBounds () для одного елемента - карта може наближатися занадто близько. Щоб це виправити, просто додайте 'maxZoom' до mapOptions ...

var mapOptions = {
  maxZoom: 15
};

7

У моєму випадку я просто хотів встановити рівень масштабування на один менше, ніж те, що вибрали для мене карти Google під час fitBounds. Метою було використовувати fitBounds, але також переконатись, що під будь-якими інструментами карт тощо не було маркерів.

Моя карта створюється рано, і тоді ряд інших динамічних компонентів сторінки мають можливість додавати маркери, викликаючи fitBounds після кожного додавання.

Це в початковому блоці, де спочатку створений об’єкт карти ...

var mapZoom = null;

Потім це додається до кожного блоку, куди додається маркер, безпосередньо перед викликом map.fitBounds ...

google.maps.event.addListenerOnce(map, 'bounds_changed', function() { 
    if (mapZoom != map.getZoom()) { 
        mapZoom = (map.getZoom() - 1); 
        map.setZoom(mapZoom); 
    } 
});

При використанні 'bounds_changed' без чека на місці, карта зменшується один раз для кожного маркера, незалежно від того, потрібен він чи ні. І навпаки, коли я використовував 'zoom_changed', я іноді мав маркери під інструментами карти, оскільки масштаб насправді не змінювався. Зараз це завжди спрацьовує, але перевірка гарантує, що воно зменшується лише один раз і лише за потреби.

Сподіваюся, це допомагає.


Здається, це єдина відповідь, яку слід насправді використовувати addListenerзамість того, щоб повторювати (і покладатися на запам'ятовування) addListenerOnceперед кожним сингломmap.fitBounds()
Flygenring

3

Оскільки Google Maps V3 керується подіями, ви можете сказати API повернути масштаб на належну величину, коли спрацьовує подія zoom_changed :

var initial = true
google.maps.event.addListener(map, "zoom_changed", function() {
    if (initial == true){
       if (map.getZoom() > 11) {
         map.setZoom(11);
         initial = false;
       }
    }
}); 

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


2

Я виявив, що наступне працює цілком приємно. Це варіант на Райана відповідь на https: //stackoverflow.com/questions/3334729 / ... . Це гарантує показ площі принаймні вдвічі більшу за значення offsetв градусах.

const center = bounds.getCenter()
const offset = 0.01
const northEast = new google.maps.LatLng(
    center.lat() + offset,
    center.lng() + offset
)
const southWest = new google.maps.LatLng(
    center.lat() - offset,
    center.lng() - offset
)
const minBounds = new google.maps.LatLngBounds(southWest, northEast)
map.fitBounds(bounds.union(minBounds))

0

Я просто мав вирішити одне і те ж завдання і використовував просту функцію для його вирішення.

байдуже, скільки маркерів знаходиться в межах - якщо їх багато, а масштабування вже далеко, це зменшує трохи, але коли є лише один маркер (або багато дуже близько один до одного) , тоді зменшення є значним (настроюється зі extendByзмінною):

var extendBounds = function() {
  // Extends the Bounds so that the Zoom Level on fitBounds() is a bit farer away
  var extendBy = 0.005;
  var point1 = new google.maps.LatLng(
    bounds.getNorthEast().lat() + extendBy,
    bounds.getNorthEast().lng() + extendBy
  )
  var point2 = new google.maps.LatLng(
    bounds.getSouthWest().lat() - extendBy,
    bounds.getSouthWest().lng() - extendBy
  )
  bounds.extend(point1);
  bounds.extend(point2);
}

Для його використання я використовую власну функцію, щоб зробити fitBounds():
map - це мій об’єкт GoogleMap

var refreshBounds = function() {
  extendBounds();
  map.fitBounds(bounds);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.