API Карт Google v3: Могу ли я установить Zoom после fitBounds?

У меня есть набор точек, которые я хочу построить на встроенной карте Google (API v3). Я бы хотел, чтобы границы учитывали все точки, если уровень масштабирования слишком низкий (т.е. Слишком сильно уменьшен). Мой подход был таким:

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

// extend bounds with each point

gmap.fitBounds(bounds); 
gmap.setZoom( Math.max(6, gmap.getZoom()) );

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

Есть ли способ получить уровень масштабирования границ без применения его к карте? Другие идеи для решения этой проблемы?

Ответ 1

Изменить. См. комментарий Matt Diamond ниже.

Получил! Попробуйте следующее:

map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() { 
  if (map.getZoom() > 16) map.setZoom(16); 
  google.maps.event.removeListener(listener); 
});

Измените ваши потребности.

Ответ 2

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

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

Решение заключалось в том, чтобы использовать fitBounds, когда было много точек, и setCenter + setZoom, когда была только одна точка.

if (pointCount > 1) {
  map.fitBounds(mapBounds);
}
else if (pointCount == 1) {
  map.setCenter(mapBounds.getCenter());
  map.setZoom(14);
}

Ответ 3

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

google.maps.event.addListenerOnce(googleMap, 'zoom_changed', function() {
    var oldZoom = googleMap.getZoom();
    googleMap.setZoom(oldZoom - 1); //Or whatever
});

В основном я обнаружил, что событие "zoom_changed" помешало UI карты "пропустить", которое произошло, когда я ждал события "без дела".

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

Ответ 4

Я просто исправил это, предварительно установив maxZoom, а затем удалив его. Например:

map.setOptions({ maxZoom: 15 });
map.fitBounds(bounds);
map.setOptions({ maxZoom: null });

Ответ 5

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

var map = new google.maps.Map(document.getElementById('map_canvas'), {
  zoom: 16,
  center: marker_point,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

Затем после этого я сделал необходимые вещи:

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

// You can have a loop here of all you marker points
// Begin loop
bounds.extend(marker_point);
// End loop

map.fitBounds(bounds);

Результат:  Успех!

Ответ 6

Я использую:

gmap.setZoom(24); //this looks a high enough zoom value
gmap.fitBounds(bounds); //now the fitBounds should make the zoom value only less

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

Ответ 7

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

  • Объявить границы
  • Использовать схему, предоставляемую koderoid (для каждого набора маркеров bounds.extend(objLatLng))
  • Выполнить подгонки ПОСЛЕ завершения карты:

    google.maps.event.addListenerOnce(map, 'idle', function() { 
        map.fitBounds( bounds );
    });
    

Ответ 8

Я нашел решение, которое выполняет проверку перед вызовом fitBounds, чтобы вы не увеличивали масштаб и не уменьшали масштаб

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

// extend bounds with each point

var minLatSpan = 0.001;
if (bounds.toSpan().lat() > minLatSpan) {
    gmap.fitBounds(bounds); 
} else {
    gmap.setCenter(bounds.getCenter());
    gmap.setZoom(16);
}

Вам придется немного поиграть с переменной minLatSpan, чтобы получить ее там, где вы хотите. Он будет меняться в зависимости от уровня масштабирования и размеров холста карты.

Вы также можете использовать долготу вместо широты

Ответ 9

Пожалуйста, попробуйте следующее:

map.fitBounds(bounds);

// CHANGE ZOOM LEVEL AFTER FITBOUNDS
zoomChangeBoundsListener = google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
  if (this.getZoom()){
    this.setZoom(15);
  }
});
setTimeout(function(){
  google.maps.event.removeListener(zoomChangeBoundsListener)
}, 2000);

Ответ 10

В этой функции вам необходимо динамически добавлять метаданные для хранения типа геометрии только потому, что функция принимает любую геометрию.

"fitGeometries" - это функция JSON, расширяющая объект карты.

"geometries" - это общий массив javascript, а не MVCArray().

geometry.metadata = { type: "point" };
var geometries = [geometry];

fitGeometries: function (geometries) {
    // go and determine the latLngBounds...
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0; i < geometries.length; i++) {
        var geometry = geometries[i];
        switch (geometry.metadata.type)
        {
            case "point":
                var point = geometry.getPosition();
                bounds.extend(point);
                break;
            case "polyline":
            case "polygon": // Will only get first path
                var path = geometry.getPath();
                for (var j = 0; j < path.getLength(); j++) {
                    var point = path.getAt(j);
                    bounds.extend(point);
                }
                break;
        }
    }
    this.getMap().fitBounds(bounds);
},

Ответ 11

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

Добавить прослушиватель в событие zoom_changed. Это также добавило преимущества управления зуммированием в пользовательском интерфейсе.

Выполняйте только setZoom, если вам нужно, поэтому оператор if предпочтительнее Math.max или Math.min

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() > 19 ) { 
        map.setZoom(19); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

Чтобы предотвратить слишком большое масштабирование:

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() < 6 ) { 
        map.setZoom(6); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

Ответ 12

У меня была такая же проблема, и я смог ее решить, используя следующий код. Событие прослушивателя (google.maps.addListenerOnce()) запускается только один раз, сразу после выполнения map.fitBounds(). Таким образом, нет необходимости

  • Отслеживать и вручную удалять слушателя, или
  • Подождите, пока карта будет idle.

Сначала он устанавливает соответствующий уровень масштабирования и позволяет пользователю увеличивать и уменьшать масштаб за предыдущий уровень масштабирования, потому что истек прослушиватель событий. Например, если был вызван только google.maps.addListener(), тогда пользователь never сможет увеличить масштаб после указанного уровня масштабирования (в случае 4). Поскольку мы реализовали google.maps.addListenerOnce(), пользователь сможет масштабировать до любого уровня, который он/она выбирает.

map.fitBounds(bounds);

var zoom_level_for_one_marker = 4;

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

Ответ 13

эта работа для меня с API v3, но с установкой фиксированного масштабирования:

var bounds = new google.maps.LatLngBounds();
// extend bounds with each point

gmap.setCenter(bounds.getCenter()); 
gmap.setZoom( 6 );

Ответ 14

Как и я, если вы не хотите играть с слушателями, это простое решение, с которым я столкнулся: Добавьте метод на карте, который работает строго в соответствии с вашими требованиями, такими как:

    map.fitLmtdBounds = function(bounds, min, max){
        if(bounds.isEmpty()) return;
        if(typeof min == "undefined") min = 5;
        if(typeof max == "undefined") max = 15;

        var tMin = this.minZoom, tMax = this.maxZoom;
        this.setOptions({minZoom:min, maxZoom:max});
        this.fitBounds(bounds);
        this.setOptions({minZoom:tMin, maxZoom:tMax});
    }

то вы можете вызвать map.fitLmtdBounds(bounds) вместо map.fitBounds(bounds), чтобы установить границы под определенным диапазоном масштабирования... или map.fitLmtdBounds(bounds,3,5), чтобы переопределить диапазон масштабирования..

Ответ 15

Я видел много неправильных или слишком сложных решений, поэтому решил опубликовать рабочее, элегантное решение.

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

Что вы могли бы подумать, это установить параметр карты minZoom перед вызовом fitBounds(), а затем очистить его после его завершения (чтобы пользователи все равно могли вручную уменьшить их, если захотят):

var bounds = new google.maps.LatLngBounds();
// ... (extend bounds with all points you want to fit)

// Ensure the map does not get too zoomed out when fitting the bounds.
gmap.setOptions({minZoom: 6});
// Clear the minZoom only after the map fits the bounds (note that
// fitBounds() is asynchronous). The 'idle' event fires when the map
// becomes idle after panning or zooming.
google.maps.event.addListenerOnce(gmap, 'idle', function() {
  gmap.setOptions({minZoom: null});
});

gmap.fitBounds(bounds);

Кроме того, если вы хотите также ограничить максимальное масштабирование, вы можете применить тот же трюк с свойством maxZoom.

Смотрите Документы MapOptions.

Ответ 16

Пожалуйста, попробуйте это.

// Find out what the map zoom level is
zoom = map.getZoom();
if (zoom == 1) {
  // If the zoom level is that low, means it looking around the
world.
  // Swap the sw and ne coords
  viewportBounds = new
google.maps.LatLngBounds(results[0].geometry.location, initialLatLng);
  map.fitBounds(viewportBounds);
}

Если это вам поможет.

Все лучшее

Ответ 17

Мне не нравится предлагать это, но если вы должны попробовать - сначала вызовите

gmap.fitBounds(bounds);

Затем создайте новую тему Thread/AsyncTask, попросите ее спать в течение 20-50 мс или около того, а затем вызовите

gmap.setZoom( Math.max(6, gmap.getZoom()) );

из потока пользовательского интерфейса (используйте обработчик или метод onPostExecute для AsyncTask).

Я не знаю, работает ли это, просто предложение. Помимо этого вам придется как-то рассчитать уровень масштабирования от ваших очков самостоятельно, проверить, слишком ли это, исправить его, а затем просто вызвать gmap.setZoom(correctedZoom)

Ответ 18

После вычисления границ вы можете проверить расстояние между верхним левым и правым нижним углом; то вы можете понять уровень масштабирования, проверив расстояние (если расстояние слишком далеко, уровень масштабирования будет низким), тогда вы можете выбрать значение с помощью метода setbound или setZoom..

Ответ 19

google.maps.event.addListener(marker, 'dblclick', function () {
    var oldZoom = map.getZoom(); 
    map.setCenter(this.getPosition());
    map.setZoom(parseInt(oldZoom) + 1);
});

Ответ 20

Если 'bounds_changed' не срабатывает правильно (иногда Google, похоже, не согласен с координатами), а затем используйте вместо этого 'center_changed'.

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

В обычных случаях "idle" по-прежнему является лучшим слушателем событий, но это может помочь парам людей, которые сталкиваются с странными проблемами с помощью своих вызовов fitBounds().

Смотрите обратный вызов google maps fitBounds

Ответ 21

Все, что я сделал, это:

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

И он работает на V3 API.