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.