Я ищу способ рассчитать уровень масштабирования для заданных границ с помощью API Google Maps V3, аналогично getBoundsZoomLevel()
API V2.
Вот что я хочу сделать:
// These are exact bounds previously captured from the map object
var sw = new google.maps.LatLng(42.763479, -84.338918);
var ne = new google.maps.LatLng(42.679488, -84.524313);
var bounds = new google.maps.LatLngBounds(sw, ne);
var zoom = // do some magic to calculate the zoom level
// Set the map to these exact bounds
map.setCenter(bounds.getCenter());
map.setZoom(zoom);
// NOTE: fitBounds() will not work
К сожалению, я не могу использовать этот fitBounds()
метод для моего конкретного случая использования. Он хорошо подходит для размещения маркеров на карте, но не подходит для установки точных границ. Вот пример того, почему я не могу использовать этот fitBounds()
метод.
map.fitBounds(map.getBounds()); // not what you expect
google-maps
google-maps-api-3
Ник Кларк
источник
источник
fitBounds()
. В этом вопросе спрашивается, что делать, когда этогоfitBounds()
недостаточно - либо из-за чрезмерного увеличения, либо из-за того, что вы не хотите увеличивать масштаб (т.е. вам просто нужен уровень масштабирования).Ответы:
Аналогичный вопрос был задан в группе Google: http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/e6448fc197c3c892
Уровни масштабирования дискретны, с увеличением в два раза на каждом шаге. В общем, вы не можете точно уместить желаемые границы (если только вам не повезет с конкретным размером карты).
Другой проблемой является соотношение сторон, например, вы не можете точно подогнать границы к тонкому прямоугольнику внутри квадратной карты.
Нет простого ответа на вопрос, как соответствовать точным границам, потому что даже если вы хотите изменить размер div карты, вам нужно выбрать, какой размер и соответствующий уровень масштабирования вы меняете (грубо говоря, делаете ли вы его больше или меньше чем сейчас?).
Если вам действительно нужно рассчитать масштаб, а не сохранить его, это должно помочь:
Проекция Меркатора искажает широту, но любая разница в долготе всегда представляет одну и ту же долю ширины карты (угловая разница в градусах / 360). При нулевом масштабировании вся карта мира имеет размер 256x256 пикселей, а масштабирование каждого уровня удваивает ширину и высоту. Итак, после небольшой алгебры мы можем вычислить масштаб следующим образом, если нам известна ширина карты в пикселях. Обратите внимание: поскольку долгота повторяется, мы должны убедиться, что угол положительный.
источник
Спасибо Джайлзу Гардаму за его ответ, но он касается только долготы, а не широты. Полное решение должно рассчитать уровень масштабирования, необходимый для широты, и уровень масштабирования, необходимый для долготы, а затем взять меньшее (дальнее) из двух.
Вот функция, которая использует широту и долготу:
Demo on jsfiddle
Параметры:
Значение параметра "bounds" должно быть
google.maps.LatLngBounds
объектом.Значение параметра «mapDim» должно быть объектом со свойствами «высота» и «ширина», которые представляют высоту и ширину элемента DOM, отображающего карту. Вы можете уменьшить эти значения, если хотите обеспечить заполнение. То есть вы не хотите, чтобы маркеры карты в границах находились слишком близко к краю карты.
Если вы используете библиотеку jQuery,
mapDim
значение можно получить следующим образом:Если вы используете библиотеку Prototype, значение mapDim можно получить следующим образом:
Возвращаемое значение:
Возвращаемое значение - это максимальный уровень масштабирования, при котором будут отображаться все границы. Это значение будет находиться в
0
диапазоне от и до максимального уровня масштабирования включительно.Максимальный уровень масштабирования - 21. (я считаю, что он был только 19 для Google Maps API v2.)
Пояснение:
Карты Google используют проекцию Меркатора. В проекции Меркатора линии долготы расположены одинаково, а линии широты - нет. Расстояние между линиями широты увеличивается по мере продвижения от экватора к полюсам. На самом деле расстояние стремится к бесконечности, когда достигает полюсов. Однако карта Google Maps не показывает широту выше примерно 85 градусов северной широты или ниже примерно -85 градусов южной широты. (для справки ) (Я рассчитал фактическое значение отсечки на +/- 85,05112877980658 градусов.)
Это усложняет вычисление дробей для границ для широты, чем для долготы. Я использовал формулу из Википедии, чтобы вычислить долю широты. Я предполагаю, что это соответствует проекции, используемой Google Maps. В конце концов, страница документации Google Maps, на которую я ссылаюсь выше, содержит ссылку на ту же страницу Википедии.
Прочие примечания:
источник
fitBounds
вам нужно создать карту, а затем дождаться события «bounds_changed».map.getProjection()
устранило бы часть математики (и предположение о проекции), но это означало бы, что функция не может быть вызвана до тех пор, пока карта не будет создана и не сработает событие "projection_changed".Для версии 3 API это просто и работает:
и несколько дополнительных приемов:
источник
maxZoom
не позволит пользователю изменять масштаб вручную . Мой пример изменяет только DefaultZoom и только если это необходимо.getBoundsZoomLevel
. таким образом, когда вы вызываете setZoom, он анимирует желаемый уровень масштабирования. оттуда не проблема сделать panTo, и вы получите красивую анимацию карты, которая соответствует границамВот версия функции Kotlin:
источник
Спасибо, это очень помогло мне найти наиболее подходящий коэффициент масштабирования для правильного отображения ломаной линии. Я нахожу максимальные и минимальные координаты среди точек, которые мне нужно отслеживать, и, если путь очень "вертикальный", я просто добавил несколько строк кода:
Фактически, идеальный коэффициент масштабирования - zoomfactor-1.
источник
var zoomfactor = Math.floor(Math.log(960 * 360 / angle / GLOBE_WIDTH) / Math.LN2)-1;
. Тем не менее, очень полезно.Поскольку все остальные ответы, похоже, вызывают у меня проблемы с тем или иным набором обстоятельств (ширина / высота карты, ширина / высота границ и т. Д.), Я решил, что поставлю здесь свой ответ ...
Здесь был очень полезный файл javascript: http://www.polyarc.us/adjust.js
Я использовал это как основу для этого:
Вы, конечно, можете очистить это или минимизировать, если необходимо, но я оставил имена переменных длинными, чтобы облегчить понимание.
Если вам интересно, откуда взялось смещение, очевидно, 268435456 - это половина окружности Земли в пикселях при уровне масштабирования 21 (согласно http://www.appelsiini.net/2008/11/introduction-to-marker-clustering-with-google -карты ).
источник
Валерио почти прав со своим решением, но есть логическая ошибка.
вы должны сначала проверить, больше ли угол 2, чем угол, прежде чем добавлять 360 при отрицательном значении.
в противном случае у вас всегда будет большее значение, чем угол
Итак, правильное решение:
Дельта есть, потому что у меня ширина больше, чем высота.
источник
map.getBounds()
не является мгновенной операцией, поэтому я использую в аналогичном случае обработчик событий. Вот мой пример в Coffeescriptисточник
Пример работы для поиска среднего центра по умолчанию с помощью react-google-maps
ES6
:источник
Расчет уровня масштабирования для долготы Джайлза Гардама у меня отлично работает. Если вы хотите рассчитать коэффициент масштабирования для широты, это простое решение, которое отлично работает:
источник
Для быстрой версии
источник
Версия Дротика:
источник