Використання setZoom () після використання fitBounds () з Google Maps API V3


79

Я використовую fitBounds () для встановлення рівня масштабування на моїй карті, включаючи всі маркери, що відображаються на даний момент. Однак, коли у мене видно лише один маркер, рівень масштабування становить 100% (... який рівень масштабування 20, я думаю ...). Однак я не хочу, щоб воно було настільки масштабованим, щоб користувач міг регулювати положення маркера без зменшення масштабу.

У мене є такий код:

var marker = this.map.createMarker(view.latlng, this.markerNumber);
this.map.bounds.extend(view.latlng);
this.map.map.setCenter(this.map.bounds.getCenter());
this.map.map.fitBounds(this.map.bounds);
if (this.markerNumber === 1) {
  this.map.map.setZoom(16);
}
this.markerNumber++;

де this.map.bounds раніше визначався як:

this.map.bounds = new google.maps.LatLngBounds();

Однак у мене проблема полягає в тому, що рядок this.map.map.setZoom(16);не працює, якщо я використовую this.map.map.fitBounds(this.map.bounds);, однак, я знаю, що рядок коду правильний, тому що коли я коментую рядок fitBound (), setZoom () магічно починає функціонувати.

Будь-які ідеї, як я можу це вирішити? Я думаю встановити рівень maxZoom як альтернативу, якщо мені не вдається це зробити.


.Map.map навмисно є чи є помилка? Якщо можливо, завантажте тестову сторінку та надайте посилання, щоб ми могли побачити проблему з більшою легкістю.
Аргіропулос Ставрос

У мене така сама проблема. Хотілося б знати виправлення.
Герман Шааф,

.map.map був там навмисно. Перший посилався на мій об’єкт карти, а другий - на об’єкт карти Google. З тих пір я видалив цю проблему зі свого коду.
Andrew De Andrade

Відповіді:


112

Гаразд, я це зрозумів. Очевидно, підбірка () відбувається асинхронно, тому вам доведеться почекати bounds_changedподії, перш ніж налаштування масштабування спрацює.

map = this.map.map;

map.fitBounds(this.map.bounds);
zoomChangeBoundsListener = 
    google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
        if (this.getZoom()){
            this.setZoom(16);
        }
});
setTimeout(function(){google.maps.event.removeListener(zoomChangeBoundsListener)}, 2000);

Оновлення : Дивіться відповідь @ Nequin за допомогою addListenerOnceкращого рішення, яке не вимагає тайм-ауту.


10
Приємне рішення, працювало і на мене. Хоча ти міг зробити те, addListenerOnce()що покінчило би з removeListener()дзвінком.
Mike Purcell

2
На додаток до використання addListenerOnce, я б порадив використовувати setTimeout для видалення слухача. У мене був випадок, коли межі не змінювались, оскільки маркери знаходились у безпосередній близькості один від одного. За допомогою цього коду користувач не зможе масштабувати (принаймні один раз).
h0tw1r3

@MikePurcell & h0tw1r3: Я відредагував код, щоб додати ваші пропозиції, дякую! Не перевіряв, тому сподіваюся, що я не допустив жодних дурних помилок.
Герман Шааф,

@Herman ..... thnx herman я зупинився на цій проблемі близько 3 годин ... thnx знову ...
Usman

1
Мені довелося помістити removeListener всередину функції зворотного виклику addListener. Інакше виконання призведе до видалення слухача ще до його виклику.
Арман Біматов

106
google.maps.event.addListenerOnce(yourMap, 'bounds_changed', function(event) {
  if (this.getZoom() > 15) {
    this.setZoom(15);
  }
});

Це рішення працює краще ... замість того, щоб чекати часу очікування, щоб видалити слухача. Зателефонуйте безпосередньо перед використанням fitBounds(я вважаю, що дзвінок після також буде працювати)


4
Хороше рішення. Може зробити це краще, використовуючи google.maps.event.addListenerOnceзамість додавання та видалення слухача.
chuck w

3
Я дозволив собі відредагувати відповідь addListenerOnce.
Mathias Bynens

1
Це рішення для мене не працює. this.getZoom () завжди не визначений у зворотному виклику, і this.setZoom () не впливає.
Горацій

Ідеальна, найкраща відповідь
00-BBB

Пам'ятайте проблеми з допомогою цього я б замість того, щоб використовувати посилання на карту , переданої в обробник події, наприклад: if (yourMap.getZoom() > 15) { ... }. Здається, у @horace були проблеми з цим, і, ймовірно, це стосується поточного класу, де здійснюється реалізація, або google.maps.eventекземпляра. Не використовуйте це, якщо ви просто хочете використовувати передане посилання на свою карту.
Sparker73,

16

Я виявив, що додаткове масштабування трохи стримує. Якщо ви встановите опцію maxZoom перед викликом fitBounds (а потім скасуєте її у зворотному виклику), ви можете уникнути цього:

map.setOptions({
    maxZoom: 10
});

map.setCenter(new google.maps.LatLng(-89, -179)); // make sure it changes so the idle listener gets called back

map.fitBounds(bounds);

var listener = google.maps.event.addListenerOnce(map, "idle", function()
{
    map.setOptions({
        maxZoom: 999
    });
});

набагато краще рішення, оскільки встановлення масштабу після зміни меж (як пропонували інші відповіді) не буде плавним, насправді буде дуже потворним.
Педро Естевао,

2

У мене є просте і брудне рішення.
Використовуйте якщо ще ...

var marker = this.map.createMarker(view.latlng, this.markerNumber);
this.map.bounds.extend(view.latlng);
this.map.map.setCenter(this.map.bounds.getCenter()); 
if (this.markerNumber === 1) {
  this.map.map.setZoom(16);
} else {
   this.map.map.fitBounds(this.map.bounds);
}       
this.markerNumber++;

1
Але чи знаєте ви, чому вони не працюють разом? Я не розумію, чому вони несумісні, якщо їх викликати послідовно.
Ендрю Де Андраде

1

Я просто додав один рядок до функції, addBounds(position)і вона виправила її, як показано нижче:

    addBounds: function(position) {
        this.get('bounds', new google.maps.LatLngBounds()).extend(this._latLng(position));
        this.get('map').fitBounds(this.get('bounds'));
        this.get('map').setZoom(16);//line added
        return this;
    },

0

Всі рішення із прослуховувачами подій для мене не працювали (this.getZoom () завжди не визначено у зворотному виклику, і this.setZoom () не впливає).

Я придумав таке рішення, яке добре працювало:

function set_zoom() {
    if(map.getZoom()) {map.setZoom(map.getZoom() - 1);}
    else {setTimeout(set_zoom, 5);}
}
setTimeout(set_zoom, 5);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.