В Maps JavaScript API возможны две реализации карт: растровая и векторная. Растровая карта загружается как сетка растровых изображений, которые генерируются на стороне сервера платформы Google Карт и затем передаются в ваше веб-приложение. Векторная карта состоит из векторных фрагментов, которые отрисовываются на стороне клиента с помощью WebGL – веб-технологии, позволяющей браузеру использовать графический процессор на устройстве пользователя для отрисовки 2D- и 3D-графики.
Векторная карта — это знакомая любому пользователю карта Google. Она функциональнее загружаемой по умолчанию растровой карты (отметим в первую очередь более высокую четкость векторных изображений и отрисовку 3D-зданий при крупном масштабе). Векторная карта поддерживает следующие функции:
- Программное управление наклоном и ориентацией
- Улучшенное управление камерой
- Дробные коэффициенты масштабирования для более плавного изменения масштаба
Для карт, загруженных с помощью элемента
divи кода JavaScript, по умолчанию используется тип отрисовкиgoogle.maps.RenderingType.RASTER.Для карт, загруженных с помощью элемента
gmp-map, по умолчанию используется тип отрисовкиgoogle.maps.RenderingType.VECTORс включенным управлением наклоном и ориентацией.
Начать работу с векторными картами
Наклон и поворот
Установить угол наклона и ориентации векторной карты можно с помощью свойств heading и tilt (при инициализации карты) и вызова методов setTilt и setHeading. В примере ниже на карту добавлено несколько кнопок для программной настройки угла наклона и ориентации с шагом 20 градусов.
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: { lat: 37.7893719, lng: -122.3942, }, zoom: 16, heading: 320, tilt: 47.5, mapId: "90f87356969d889c", } ); const buttons: [string, string, number, google.maps.ControlPosition][] = [ ["Rotate Left", "rotate", 20, google.maps.ControlPosition.LEFT_CENTER], ["Rotate Right", "rotate", -20, google.maps.ControlPosition.RIGHT_CENTER], ["Tilt Down", "tilt", 20, google.maps.ControlPosition.TOP_CENTER], ["Tilt Up", "tilt", -20, google.maps.ControlPosition.BOTTOM_CENTER], ]; buttons.forEach(([text, mode, amount, position]) => { const controlDiv = document.createElement("div"); const controlUI = document.createElement("button"); controlUI.classList.add("ui-button"); controlUI.innerText = `${text}`; controlUI.addEventListener("click", () => { adjustMap(mode, amount); }); controlDiv.appendChild(controlUI); map.controls[position].push(controlDiv); }); const adjustMap = function (mode: string, amount: number) { switch (mode) { case "tilt": map.setTilt(map.getTilt()! + amount); break; case "rotate": map.setHeading(map.getHeading()! + amount); break; default: break; } }; } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 37.7893719, lng: -122.3942, }, zoom: 16, heading: 320, tilt: 47.5, mapId: "90f87356969d889c", }); const buttons = [ ["Rotate Left", "rotate", 20, google.maps.ControlPosition.LEFT_CENTER], ["Rotate Right", "rotate", -20, google.maps.ControlPosition.RIGHT_CENTER], ["Tilt Down", "tilt", 20, google.maps.ControlPosition.TOP_CENTER], ["Tilt Up", "tilt", -20, google.maps.ControlPosition.BOTTOM_CENTER], ]; buttons.forEach(([text, mode, amount, position]) => { const controlDiv = document.createElement("div"); const controlUI = document.createElement("button"); controlUI.classList.add("ui-button"); controlUI.innerText = `${text}`; controlUI.addEventListener("click", () => { adjustMap(mode, amount); }); controlDiv.appendChild(controlUI); map.controls[position].push(controlDiv); }); const adjustMap = function (mode, amount) { switch (mode) { case "tilt": map.setTilt(map.getTilt() + amount); break; case "rotate": map.setHeading(map.getHeading() + amount); break; default: break; } }; } window.initMap = initMap;
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } .ui-button { background-color: #fff; border: 0; border-radius: 2px; box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3); margin: 10px; padding: 0 0.5em; font: 400 18px Roboto, Arial, sans-serif; overflow: hidden; height: 40px; cursor: pointer; } .ui-button:hover { background: rgb(235, 235, 235); }
HTML
<html>
<head>
<title>Tilt and Rotation</title>
<link rel="stylesheet" type="text/css" href="./style.css" />
<script type="module" src="./index.js"></script>
</head>
<body>
<div id="map"></div>
<!--
The `defer` attribute causes the script to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises. See
https://developers.google.com/maps/documentation/javascript/load-maps-js-api
for more information.
-->
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
defer
></script>
</body>
</html>Настройка с помощью мыши и клавиатуры
Если включены пользовательские взаимодействия с наклоном и поворотом (ориентацией) (программно или в консоли Google Cloud), пользователи могут настраивать наклон и поворот с помощью мыши и клавиатуры.
- Мышь: удерживая клавишу Shift, перетаскивайте карту мышью вверх и вниз, чтобы отрегулировать угол наклона, или вправо и влево, чтобы отрегулировать ориентацию.
- Клавиатура: удерживая клавишу Shift, нажимайте стрелки вверх и вниз, чтобы отрегулировать угол наклона, или стрелки вправо и влево, чтобы отрегулировать ориентацию.
Программная настройка угла наклона и ориентации
Настроить углы наклона и ориентации векторной карты можно с помощью методов setTilt() и setHeading(). Ориентация задается как угол обзора в градусах от направления на север по часовой стрелке (т. е. код map.setHeading(90) сориентирует карту верхом на восток). Угол наклона отсчитывается от оси, направленной в сторону зенита: коду map.setTilt(0) соответствует стандартный вид сверху вниз, а коду map.setTilt(45) – вид под углом.
- Вызывайте метод
setTilt(), чтобы задать угол наклона карты, аgetTilt()– чтобы получить его текущее значение. - Вызывайте метод
setHeading(), чтобы задать угол ориентации карты, аgetHeading()– чтобы получить его текущее значение.
Чтобы изменить центральную точку карты, сохранив текущий угол наклона и ориентации, используйте метод map.setCenter() или map.panBy().
Учтите, что допустимый диапазон значений углов зависит от масштаба карты. Если заданное значение окажется за пределами диапазона, вместо него будет применено ближайшее допустимое.
Изменить программно ориентацию, наклон, центр и масштаб карты можно также с помощью метода moveCamera.
Подробнее…
Влияние на другие методы
Заданные для карты значения угла наклона и ориентации влияют на поведение других методов Maps JavaScript API.
- Метод
map.getBounds()всегда возвращает самую маленькую граничную рамку, которая включает видимую область; при применении наклона возвращаемые границы могут представлять более обширную область, чем видимая область просмотра карты. - Метод
map.fitBounds()обнуляет значения угла ориентации и наклона, прежде чем сузить карту. - Метод
map.panToBounds()обнуляет значения угла ориентации и наклона, прежде чем расширить карту. - Метод
map.setTilt()принимает любые значения, но выдает угол наклона только в рамках допустимого для текущего масштаба карты диапазона. map.setHeading()принимает любые значения и приводит их к диапазону[0, 360].
Управление камерой
Используйте метод map.moveCamera() для одновременного обновления свойств камеры в любых сочетаниях. Все свойства камеры, которые нужно изменить, передаются методу map.moveCamera() в одном параметре. В примере ниже показан вызов map.moveCamera() для одновременной настройки свойств center, zoom, heading и tilt.
map.moveCamera({
center: new google.maps.LatLng(37.7893719, -122.3942),
zoom: 16,
heading: 320,
tilt: 47.5
});
Вы можете анимировать картинку, поступающую с камеры, вызвав метод map.moveCamera() и запустив цикл, как показано в примере ниже.
const degreesPerSecond = 3;
function animateCamera(time) {
// Update the heading, leave everything else as-is.
map.moveCamera({
heading: (time / 1000) * degreesPerSecond
});
requestAnimationFrame(animateCamera);
}
// Start the animation.
requestAnimationFrame(animateCamera);
Позиция камеры
Модель представления карты предполагает направление камеры вниз на плоскость. Положение камеры (и, следовательно, отрисовка карты) указывается с помощью следующих свойств: цель (широта и долгота), азимут, наклон и масштаб.
Цель камеры (местоположение)
Цель камеры – это местоположение, которое должно быть в центре карты. Оно задается широтой и долготой.
Широта может принимать значение от -85 до 85 градусов включительно. Значения, лежащие за пределами этого диапазона, отсекаются до ближайших граничных. Например, если для широты указано число 100, то это значение будет уменьшено до 85. Долгота может принимать значение от -180 до 180 градусов включительно. Значения, которые находятся вне указанного диапазона, пересчитываются так, чтобы уместиться в него (-180, 180). Например, 480, 840 и 1200 градусов после пересчета будут равны 120 градусам.Азимут (ориентация)
Азимут камеры указывается как направление по компасу, измеряемое в градусах отклонения от географического севера, который соответствует верхнему краю карты. Если нарисовать вертикальную линию от центра карты до ее верхнего края, азимут соответствует отклонению камеры в градусах от этой линии.
Нулевой азимут означает, что верхний край карты соответствует географическому северу. Значение 90 означает, что верхний край карты соответствует востоку (90 градусов на компасе), а 180 – югу.
Maps API позволяет менять азимут карты. Если вы едете на автомобиле и хотите свериться с картой, скорее всего, вы повернете ее в направлении движения. Однако в пешем походе карту лучше расположить так, чтобы север был вверху, как и на компасе.
Наклон (угол обзора)
Угол наклона определяется положением камеры на дуге над центром карты. Он измеряется в градусах относительно надира – направления, указывающего строго вниз от камеры. Нулевое значение соответствует камере, направленной вертикально вниз. Значения больше нуля соответствуют наклону камеры по направлению к линии горизонта на указанное количество градусов. При изменении угла наклона применяется эффект перспективы, т. е. близкие объекты выглядят крупнее, а далекие – мельче. Этот эффект проиллюстрирован ниже.
На рисунках ниже угол обзора составляет 0 градусов. На рисунке справа наклон представлен схематически: 1 – это положение камеры, а 2 – положение карты. Полученная карта показана ниже.
|
|
На приведенных ниже рисунках угол обзора равен 45 градусам. Обратите внимание, что камера смещается в центр дуги, соединяющей точку зенита (0 градусов) с земной поверхностью (90 градусов). Положение камеры обозначено цифрой 3. Она по-прежнему направлена в центр карты, но теперь пользователю также становится видна область 4.
|
|
На этом скриншоте центр карты по-прежнему находится в той же точке, что и на исходной карте, но теперь в ее верхней части показано больше объектов. Если увеличивать угол обзора и далее, то размер объектов, которые расположены ближе к камере, будет пропорционально увеличиваться, а размер удаленных объектов – уменьшаться, создавая ощущение перспективы.
Масштаб
Уровень масштабирования камеры определяет масштаб карты. Чем он выше, тем больше деталей можно рассмотреть, зато при уменьшении масштаба на экране умещается большая территория.
Значение уровня масштабирования может быть не целым числом. Диапазон допустимых значений зависит от ряда критериев, таких как тип карты, целевое местоположение и размер экрана. Число за пределами этого диапазона преобразуется в ближайшее допустимое значение, то есть минимальное или максимальное значение уровня масштабирования. В списке ниже показан примерный уровень детализации, который можно ожидать на каждом уровне масштабирования:
- 1: мир;
- 5: континент;
- 10: город;
- 15: улицы;
- 20: здания.
|
|
|
Дробные коэффициенты масштабирования
В векторных картах коэффициенты масштабирования могут принимать дробные, а не только целочисленные значения. Растровые карты тоже поддерживают эту возможность, но по умолчанию она в них отключена. Включить или выключить ее можно с помощью свойства карты isFractionalZoomEnabled.
В примере ниже показано включение дробных коэффициентов масштабирования при инициализации карты.
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8,
isFractionalZoomEnabled: true
});
Вы также можете включить или выключить дробные коэффициенты масштабирования, задав свойство карты isFractionalZoomEnabled, как показано ниже.
// Using map.set
map.set('isFractionalZoomEnabled', true);
// Using map.setOptions
map.setOptions({isFractionalZoomEnabled: true});
Если вы явно не присвоили свойству isFractionalZoomEnabled значение true или false, настройте для него прослушиватель, как показано в примере ниже.
map.addListener('isfractionalzoomenabled_changed', () => {
const isFractionalZoomEnabled = map.get('isFractionalZoomEnabled');
if (isFractionalZoomEnabled === false) {
console.log('not using fractional zoom');
} else if (isFractionalZoomEnabled === true) {
console.log('using fractional zoom');
} else {
console.log('map not done initializing yet');
}
});