Google Maps v3 fitBounds() Увеличить слишком близко для одного маркера

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

Спасибо заранее!

Ответ 1

Мне нравится решение mrt (особенно, когда вы не знаете, сколько очков вы будете сопоставлять или настраиваете), кроме того, что он отбрасывает маркер, чтобы он больше не находился в центре карты. Я просто расширил его дополнительным вычитанием точки .01 из lat и lng, поэтому он удерживает маркер в центре. Отлично работает, спасибо mrt!

// Pan & Zoom map to show all markers
function fitToMarkers(markers) {

    var bounds = new google.maps.LatLngBounds();

    // Create bounds from markers
    for( var index in markers ) {
        var latlng = markers[index].getPosition();
        bounds.extend(latlng);
    }

    // Don't zoom in too far on only one marker
    if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
       var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
       var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - 0.01, bounds.getNorthEast().lng() - 0.01);
       bounds.extend(extendPoint1);
       bounds.extend(extendPoint2);
    }

    map.fitBounds(bounds);

    // Adjusting zoom here doesn't work :/

}

Ответ 2

Вы можете настроить свою карту с помощью maxZoom в MapOptions (api-reference) как это сделать:

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

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

Ответ 3

Другим решением является расширение границ, если вы обнаружите, что они слишком малы, прежде чем выполнить функцию fitBounds():

var bounds = new google.maps.LatLngBounds();
// here you extend your bound as you like
// ...
if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
   var extendPoint = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
   bounds.extend(extendPoint);
}
map.fitBounds(bounds);

Ответ 4

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

Использование опции MaxZoom лучше всего подходит для не масштабирования, чтобы закрыть метки, которые у вас есть.

Ответ 5

Если это для одного места, вы можете использовать setCenter() и setZoom().

Ответ 6

u может использовать

map.setOptions({
    maxZoom: [what u want],
    minZoom: [what u want]
});

Таким образом, u задает свойства карты после инициализации карты.... u может установить их столько раз, сколько хотите... но в случае ур... u может установить их перед fitBounds()

Удачи, rarutu

Ответ 7

То, как я не позволяю карте приближаться к далеке, добавляет эту строку кода:

var zoomOverride = map.getZoom();
        if(zoomOverride > 15) {
        zoomOverride = 15;
        }
      map.setZoom(zoomOverride);

Непосредственно после этой строки:

map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));

Не забудьте изменить уровень масштабирования на любой уровень, на который вы не хотите, чтобы карта приближалась.

Если у вас есть какие-либо проблемы или вопросы, просто оставьте мне комментарий к сообщению в блоге, которое я написал об этом на http://icode4you.net/creating-your-own-store-locator-map-how-to-prevent-the-map-from-zooming-in-too-close-on-a-single-marker

Ответ 8

Как только вы добавили все реальные границы, добавьте эти строки

var offset = 0.002;     
var center = bounds.getCenter();                            
bounds.extend(new google.maps.LatLng(center.lat() + offset, center.lng() + offset));
bounds.extend(new google.maps.LatLng(center.lat() - offset, center.lng() - offset));

он получает центр реальных границ, затем добавляет две дополнительные точки на северо-восток и одну к юго-западу от вашего центра.

Это эффективно устанавливает минимальное масштабирование, изменение значения смещения для увеличения или уменьшения увеличения

Ответ 9

Мне очень нравится решение mrt, и он отлично работает, если у вас всегда есть только один пункт для работы. Тем не менее, я обнаружил, что если ограничивающая рамка не была основана на одной точке, но точки были очень близки друг к другу, это все равно могло привести к увеличению масштаба карты.

Здесь можно сначала проверить, находятся ли точки на определенном расстоянии друг от друга, тогда, если они меньше этого минимального расстояния, расширьте границы на это минимальное расстояние:

var bounds = new google.maps.LatLngBounds();
// here you extend your bound as you like

// ...

var minDistance = 0.002;
var sumA = bounds.getNorthEast().lng() - bounds.getSouthWest().lng();
var sumB = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();

if((sumA < minDistance && sumA > -minDistance) 
&& (sumB < minDistance && sumB > -minDistance)){
var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + minDistance, bounds.getNorthEast().lng() + minDistance);
    var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - minDistance, bounds.getNorthEast().lng() - minDistance);
    bounds.extend(extendPoint1);
    bounds.extend(extendPoint2);
}

Надеюсь, это поможет кому-то!

Ответ 10

Это дает вам прямой контроль над максимально допустимым масштабированием при установке границ.

var fitToMarkers = function(map, markers, maxZoom) {
    if (typeof maxZoom == 'undefined') maxZoom = 15;

    google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
        if (this.getZoom() > maxZoom) {
            this.setZoom(maxZoom);
        }
    });

    var bounds = new google.maps.LatLngBounds();
    for (var m = 0; m < markers.length; m++) {
        var marker = markers[m];
        var latlng = marker.getPosition();
        bounds.extend(latlng);
    }

    map.fitBounds(bounds);
};

Ответ 11

Я решил с этим куском, поскольку Google Maps V3 управляется событиями:

вы можете сказать API, чтобы вернуть масштаб к правильной сумме при срабатывании события zoom_changed:

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

Я использовал intial, чтобы карта не увеличивала слишком большую загрузку, когда возможное соответствие fitBounds, без какого-либо события масштабирования более 11, было бы невозможно для пользователя.

Ответ 12

У меня есть душа, основанная на ограничении максимального увеличения при установке границ. Работает для меня (тестируется на Win 7 - IE 9, FF 13, Chrome 19):

// When fitting bounds:
var bounds = new google.maps.LatLngBounds();
// ...
// extend bounds as you like
// ..

// now set global variable when fitting bounds
window.fittingBounds = true;
map.fitBounds(bounds);
window.fittingBounds = false;


// attach this event listener after map init
google.maps.event.addListener(map, 'zoom_changed', function() {
    // set max zoom only when fitting bounds
    if (window.fittingBounds && map.getZoom() > 16) {
        this.setZoom(16);
    }
});

Ответ 13

И.. вот еще один.
Такая же идея, как mrt и Ryan, но

  • также работает, если размер границ не равен нулю (*)
  • предотвращает искажение вблизи полюсов
  • использует getCenter() вместо getNorthEast()

(*) Примечание. Если ящик уже достаточно большой, то добавление этих двух дополнительных точек не должно иметь никакого эффекта. Поэтому нам не нужна дальнейшая проверка.

function calcBounds(markers) {
  // bounds that contain all markers
  var bounds = new google.maps.LatLngBounds();
  // Using an underscore _.each(). Feel free to replace with standard for()
  _.each(markers, function(marker) {
    bounds.extend(marker.getPosition());
  });
  // prevent lat/lng distortion at the poles
  var lng0 = bounds.getNorthEast().lng();
  var lng1 = bounds.getSouthWest().lng();
  if (lng0 * lng1 < 0) {
    // Take the cos at the equator.
    var cos = 1;
  }
  else {
    var cos0 = Math.cos(lng0);
    var cos1 = Math.cos(lng1);
    // Prevent division by zero if the marker is exactly at the pole.
    var cos_safe = Math.max(cos0, cos1, 0.0001);
  }
  var cos0 = Math.cos(bounds.getNorthEast.lng() * Math.PI / 180);
  var cos1 = Math.cos(bounds.getSouthWest.lng() * Math.PI / 180);
  // "radius" in either direction.
  // 0.0006 seems to be an ok value for a typical city.
  // Feel free to make this value a function argument.
  var rLat = 0.0006;
  var rLng = rLat / cos_safe;
  // expand the bounds to a minimum width and height
  var center = bounds.getCenter();
  var p0 = new google.maps.LatLng(center.lat() - rLat, center.lng() - rLng);
  var p1 = new google.maps.LatLng(lat.center() + rLat, center.lng() + rLng);
  bounds.extend(p0);
  bounds.extend(p1);
  return bounds;
}

РЕДАКТИРОВАТЬ: Я не совсем уверен, правильно ли вычисляется соотношение, учитывая, что у нас есть проекция Меркатора. Я мог бы изменить его.

Ответ 14

Он уже ответил здесь Google Maps v3: Enforcing min. уровень масштабирования при использовании fitBounds работает так, как ожидалось:), так что теперь, если после рамки рамки масштабирование будет меньше, тогда скажем 13, тогда вы можете установить новый масштаб, который вы предпочитаете

Ответ 15

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

Ответ 16

Что касается меня, ребята, я решаю его, создавая незанятое событие после fitBounds. Работает отлично. Угадайте, что одно из самых чистых решений здесь.

var locations = [['loc', lat, lng], ['loc', lat, lng]];
.....
for (i = 0; i < locations.length; i++) { 
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 10
  });
  .... create markers, etc.
}
....
map.fitBounds(bounds);  
google.maps.event.addListenerOnce(map, 'idle', function() {
  if (locations.length == 1) {
    map.setZoom(11);
  }
});