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

93

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

Заранее спасибо!

Codey W
источник
2
stackoverflow.com/questions/4523023/… - гораздо лучшее решение. Частный ответ @Nequins
Кеннет

Ответы:

139

Мне нравится решение mrt (особенно, когда вы не знаете, сколько точек вы будете отображать или настраивать), за исключением того, что оно сбрасывает маркер, так что он больше не находится в центре карты. Я просто расширил его на дополнительную точку, вычтя 0,01 из широты и долготы, так что маркер остается в центре. Отлично работает, спасибо 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 :/

}
Райан
источник
4
Хорошая идея сохранить исходный центр. Причина, по которой уровень масштабирования не может быть надежно отрегулирован при использовании fitBounds()метода, заключается в том, что масштабирование происходит асинхронно: stackoverflow.com/questions/2989858/…
Metro Smurf
1
Это отлично сработало для меня. Мне пришлось передать ссылку на карту в функцию «function fitToMarkers (markers, map)» на V3, но после этого она работает как шарм!
Шейн
4
Люби это. Хороший @ryan. У меня отлично сработало, но 0,01 в моем случае было слишком большим, 0,001 попал в золотую середину.
willdanceforfun 02
Спасибо. Как и @willdanceforfun в том же случае, 001 попал в точку.
Горан Яковлевич
1
Я бы порекомендовал это решение stackoverflow.com/questions/2437683/…
NinjaOnSafari
40

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

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

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

Flygenring
источник
@candlejack Так точно, как описано в моем ответе?
Flygenring
8
Вы можете установить maxZoomдо установки границ , а затем сбросить его снова , используя map.setOptions({ maxZoom: undefined })на idleсобытия произвели за счет изменения границ. Это предотвращает эффект увеличения и уменьшения масштаба вместо сброса масштаба idleсобытия.
Эль Йобо
29

Другое решение - расширить границы, если вы обнаружите, что они слишком малы, прежде чем выполнять 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);
mrt
источник
19
var map = new google.maps.Map(document.getElementById("map"), { maxZoom: 10 });

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

Markvaneijk
источник
Фантастика! Спасатель жизни!
Jaypee
18

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

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

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

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

PWHIT
источник
12

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

CrazyEnigma
источник
самое простое решение
Alberto M
11

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

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

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

удачи, раруту

Wowzaaa
источник
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- карта-из-увеличения-слишком-близко-на-единственном маркере

TheLibzter
источник
1
Мне нравится это решение, но вставьте setzoom внутрь if, чтобы не вызывать его каждый раз. Также может быть побочный эффект времени, который возвращает undefined из getzoom (). Решение: zoom = map.getZoom (); if (typeof zoom! == 'undefined' && zoom> 8) map.setZoom (8);
Le Droid
5

Мне очень нравится решение 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);
}

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

Упаковка
источник
3

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

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);
};
климат
источник
3

Что касается меня, ребята, я решил это, создав событие простоя после 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);
  }
});
Виталий Протосовицкий
источник
2

Я решил с помощью этого фрагмента, поскольку 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 было бы невозможно для пользователя.

настроен
источник
1

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

монещары
источник
0

У меня есть принцип, основанный на ограничении максимального увеличения при подборе границ. У меня работает (проверено на 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);
    }
});
маффир
источник
0

И .. вот еще один.
Та же идея, что и 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;
}

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

Дон Кихот
источник
0

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

Владимир Билячат
источник
-1

Вот мое решение, которое также работает, когда два маркера находятся очень близко. Эффективный максимальный уровень масштабирования одинаков в обеих ситуациях. Таким образом, мы не уменьшаем масштаб без необходимости, когда имеется более одного маркера.

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

Я заранее рассчитал maxLat, minLat, maxLng и minLng ...

var minLatSpan = 0.002;
if (maxLat - minLat < minLatSpan) {
  // ensures that we do not zoom in too much
  var delta = (minLatSpan - (maxLat - minLat)) / 2;
  maxLat += delta;
  minLat -= delta;
}

map.fitBounds({
  east: maxLng,
  west: minLng,
  north: maxLat,
  south: minLat,
});
rosell.dk
источник