Google Maps v3: Enforcing min. уровень масштабирования при использовании fitBounds

Я рисую серию маркеров на карте (используя v3 карт api).

В v2 у меня был следующий код:

  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, похоже, влияет на карту. Я что-то упускаю? Есть ли способ сделать это?

Ответ 1

Во время этого обсуждения групп Google я обнаружил, что в основном, когда вы делаете 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);

Надеюсь, это поможет,

Энтони.

Ответ 2

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

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

Если вы попытались это сделать, и это не сработало, вы можете настроить свою карту с помощью minZoom в MapOptions (api- ссылка) следующим образом:

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

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

Ответ 3

Решение Anthony очень приятно. Мне нужно было только исправить масштаб для загрузки на странице (убедитесь, что вы не слишком далеко увеличены для начала), и это сделало трюк для меня:

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 );

Ответ 4

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

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

Ответ 5

Когда вы вызываете map.fitBounds() на один элемент - карта может приближаться слишком близко. Чтобы исправить это, просто добавьте "maxZoom" в mapOptions...

var mapOptions = {
  maxZoom: 15
};

Ответ 6

В моем случае я просто хотел установить уровень масштабирования на один меньше, чем то, что карты 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", иногда у меня были маркеры в инструментах карты, потому что масштаб не изменился. Теперь он всегда срабатывает, но проверка гарантирует, что он только масштабируется один раз и только при необходимости.

Надеюсь, что это поможет.

Ответ 7

Так как 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.

Ответ 8

Я нашел следующее, чтобы работать довольно хорошо. Это вариант ответа Райана на fooobar.com/info/88392/... Это гарантирует показ области, по крайней мере, в два раза превышающей значение 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))