API карт Google 3 уменьшает масштаб на fitBounds - PullRequest
8 голосов
/ 17 ноября 2011

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

Я заметил, что вызов map.fitBounds(map.getBounds()) в консоли всегда уменьшит масштаб.Где, как мне хотелось бы, чтобы карта не менялась.

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

Спасибо

Ответы [ 6 ]

12 голосов
/ 18 ноября 2011

Эта проблема API Google Map обсуждалась несколько раз. См:

Функция map.fitBounds() устанавливает область просмотра, чтобы содержать границы. Но функция map.getBounds() возвращает границы области просмотра с некоторым дополнительным полем (обратите внимание, что это нормальное поведение и никаких ошибок). Увеличенные границы больше не вписываются в предыдущий видовой экран, поэтому карта уменьшается.

Простое решение вашей проблемы - вместо этого использовать центр карты и уровень масштабирования. См. Функции map.getCenter(), map.setCenter(), map.getZoom() и map.setZoom().

4 голосов
/ 20 января 2017

Исправление этой проблемы в 2017 году

Слегка сожмите ограничивающий прямоугольник перед отправкой на map.fitBounds().

Вот функция для сокращения ограничивающей рамки:

// Values between 0.08 and 0.28 seem to work
// Any lower and the map will zoom out too much
// Any higher and it will zoom in too much
var BOUNDS_SHRINK_PERCENTAGE = 0.08; // 8%

/**
 * @param  {google.maps.LatLngLiteral} southwest
 * @param  {google.maps.LatLngLiteral} northeast
 * @return {Array[google.maps.LatLngLiteral]}
 */
function slightlySmallerBounds(southwest, northeast) {
  function adjustmentAmount(value1, value2) {
    return Math.abs(value1 - value2) * BOUNDS_SHRINK_PERCENTAGE;
  }

  var latAdjustment = adjustmentAmount(northeast.lat, southwest.lat);
  var lngAdjustment = adjustmentAmount(northeast.lng, southwest.lng);

  return [
    {lat: southwest.lat + latAdjustment, lng: southwest.lng + lngAdjustment},
    {lat: northeast.lat - latAdjustment, lng: northeast.lng - lngAdjustment}
  ]
}

Используйте это так:

// Ensure `southwest` and `northwest` are objects in google.maps.LatLngLiteral form:
// southwest == {lat: 32.79712, lng: -117.13931}
// northwest == {lat: 32.85020, lng: -117.09356}

var shrunkBounds = slightlySmallerBounds(southwest, northeast);
var newSouthwest = shrunkBounds[0];
var newNortheast = shrunkBounds[1];

// `map` is a `google.maps.Map`
map.fitBounds(
  new google.maps.LatLngBounds(newSouthwest, newNortheast)
);

У меня есть приложение, которое делает то же самое, что и codr : сохранение границ текущей карты в URL и инициализация карты из границ URL при обновлении. Это решение прекрасно работает для этого.

Почему это работает?

Google Maps, по сути, делает это, когда fitBounds() называется:

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

Если указанные границы будут в точности соответствовать области просмотра, Google Maps не считает, что они "содержат" границы, поэтому он уменьшает еще один уровень.

3 голосов
/ 08 марта 2018

Для людей, видящих этот вопрос в 2018 году, API Карт Google v3 теперь поддерживает второй аргумент padding, который задает количество отступов, которое будет включено в указанные вами границы.

Чтобы избежать уменьшения, просто наберите fitBounds с отступом 0.Для этого примера это будет map.fitBounds(map.getBounds(), 0)

0 голосов
/ 05 июня 2019

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

<div [hidden]="view !== 'map'>
    <google-map></google-map>
</div>

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

Решение было простым: при переключении вида снова вызовите fitBounds().

<button (click)="showMap()">Show Map</button>

public showMap() {
    this.view = 'map';
    setTimeout(() => {
        if (typeof this.map !== 'undefined') this.map.fitBounds(this.bounds);
    });
}

Примечание. Я обернул setTimeout вокруг вызова fitBounds(), чтобы Angular мог завершить жизненный цикл и отобразить карту до ее вызова.

0 голосов
/ 04 февраля 2019

Я столкнулся с той же проблемой, и ответ @ Tomik помог мне решить ее. Вот фрагменты кода, который я использовал.

Для сохранения предыдущего увеличения и центра.

const lastMapZoom = this.map.getZoom();
const lastMapCenter = this.map.getCenter();

Для возврата значений.

this.map.setCenter(lastMapZoom);
this.map.setZoom(lastMapCenter);
0 голосов
/ 02 ноября 2012

Я тоже заметил эту проблему.Мое решение - сравнить map.getBounds() с тем, на что я устанавливаю границы;если они одинаковые, я пропускаю вызов map.fitBounds().

...