Advanced Markers — современный механизм отображения
маркеров в Google Maps JavaScript API, пришедший на смену классическому
классу google.maps.Marker. Новая система предоставляет
значительно более широкие возможности кастомизации внешнего вида,
улучшенную производительность и удобную интеграцию с HTML и CSS.
Основным классом выступает
google.maps.marker.AdvancedMarkerElement, позволяющий
создавать маркеры на основе DOM-элементов, использовать сложное
оформление и внедрять интерактивные пользовательские компоненты
непосредственно на карту.
Традиционные маркеры долгое время были основным способом отображения объектов на карте. Однако с ростом требований к интерфейсам появились ограничения:
Advanced Markers решают эти проблемы благодаря использованию современных веб-технологий.
Основные преимущества:
Для работы необходимо подключить библиотеку marker.
const { Map } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement } =
await google.maps.importLibrary("marker");
Создание карты:
const map = new Map(document.getElementById("map"), {
center: {
lat: 55.7558,
lng: 37.6176
},
zoom: 12,
mapId: "DEMO_MAP_ID"
});
Параметр mapId является обязательным для большинства
сценариев использования Advanced Markers.
Минимальный пример:
const marker = new AdvancedMarkerElement({
map: map,
position: {
lat: 55.7558,
lng: 37.6176
}
});
Маркер сразу отображается на карте после создания.
Карта, на которой отображается маркер.
const marker = new AdvancedMarkerElement({
map: map
});
Координаты объекта.
position: {
lat: 55.7558,
lng: 37.6176
}
Также поддерживается объект LatLng.
position: new google.maps.LatLng(
55.7558,
37.6176
)
Текстовая подсказка.
const marker = new AdvancedMarkerElement({
map,
position,
title: "Москва"
});
Текст отображается при наведении курсора.
Позволяет использовать собственный DOM-элемент.
const div = document.createElement("div");
div.textContent = "Офис";
const marker = new AdvancedMarkerElement({
map,
position,
content: div
});
Именно свойство content превращает Advanced Marker в
мощный инструмент кастомизации.
Google предоставляет готовый класс PinElement,
позволяющий быстро создавать стилизованные маркеры.
const { PinElement } =
await google.maps.importLibrary("marker");
Создание пина:
const pin = new PinElement();
const marker = new AdvancedMarkerElement({
map,
position,
content: pin.element
});
const pin = new PinElement({
background: "#4285F4"
});
const pin = new PinElement({
borderColor: "#1A73E8"
});
const pin = new PinElement({
glyphColor: "#FFFFFF"
});
const pin = new PinElement({
background: "#FF5722",
borderColor: "#BF360C",
glyphColor: "#FFFFFF"
});
Свойство glyph позволяет размещать символы или
текст.
const pin = new PinElement({
glyph: "A"
});
Результат:
[A]
Можно использовать цифры:
glyph: "1"
Или эмодзи:
glyph: "?"
Свойство scale управляет размером.
const pin = new PinElement({
scale: 1.5
});
Уменьшение:
const pin = new PinElement({
scale: 0.8
});
Одним из главных преимуществ Advanced Markers является возможность использовать произвольную HTML-разметку.
const markerElement =
document.createElement("div");
markerElement.classList.add("office-marker");
markerElement.innerHTML = `
<strong>Главный офис</strong>
`;
CSS:
.office-marker {
background: white;
border-radius: 8px;
padding: 10px 15px;
box-shadow: 0 2px 10px rgba(0,0,0,.3);
border: 1px solid #ddd;
font-size: 14px;
}
Создание маркера:
new AdvancedMarkerElement({
map,
position,
content: markerElement
});
Практический пример отображения информации.
const card = document.createElement("div");
card.innerHTML = `
<div class="place-card">
<h3>Ресторан</h3>
<p>Итальянская кухня</p>
</div>
`;
CSS:
.place-card {
width: 180px;
background: white;
border-radius: 12px;
padding: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,.15);
}
.place-card h3 {
margin: 0 0 6px;
}
Использование:
new AdvancedMarkerElement({
map,
position,
content: card
});
Внутрь маркера можно помещать изображения.
const container =
document.createElement("div");
container.innerHTML = `
<img
src="store.jpg"
width="80"
height="80"
>
`;
Создание:
new AdvancedMarkerElement({
map,
position,
content: container
});
HTML-маркер может содержать кнопки и формы.
const panel = document.createElement("div");
panel.innerHTML = `
<button id="detailsBtn">
Подробнее
</button>
`;
После добавления в DOM:
setTimeout(() => {
document
.getElementById("detailsBtn")
.addEventListener("click", () => {
alert("Информация");
});
}, 0);
marker.addListener("click", () => {
console.log("Маркер нажат");
});
marker.addListener("click", () => {
map.panTo(marker.position);
map.setZoom(16);
});
marker.addListener("click", () => {
console.log(
marker.position.lat,
marker.position.lng
);
});
Маркер можно перемещать динамически.
marker.position = {
lat: 59.9386,
lng: 30.3141
};
Или:
marker.position =
new google.maps.LatLng(
59.9386,
30.3141
);
Удаление производится отсоединением от карты.
marker.map = null;
Повторное отображение:
marker.map = map;
Скрытие:
marker.map = null;
Показ:
marker.map = map;
Такой подход заменяет методы setVisible() классических
маркеров.
Создание массива объектов:
const locations = [
{ lat: 55.75, lng: 37.61 },
{ lat: 55.77, lng: 37.63 },
{ lat: 55.74, lng: 37.60 }
];
Генерация:
locations.forEach(location => {
new AdvancedMarkerElement({
map,
position: location
});
});
Для группировки большого количества объектов применяется Marker Clusterer.
Установка:
<script src="
https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js">
</script>
Создание массива:
const markers = locations.map(location => {
return new AdvancedMarkerElement({
position: location
});
});
Кластеризация:
new markerClusterer.MarkerClusterer({
map,
markers
});
Кластеры позволяют эффективно отображать тысячи объектов без снижения производительности.
HTML-маркеры прекрасно работают с CSS.
.pulse-marker {
width: 20px;
height: 20px;
background: red;
border-radius: 50%;
animation:
pulse 1.5s infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
Создание:
const markerNode =
document.createElement("div");
markerNode.className =
"pulse-marker";
new AdvancedMarkerElement({
map,
position,
content: markerNode
});
SVG позволяет создавать полностью масштабируемые маркеры.
const svg = document.createElement("div");
svg.innerHTML = `
<svg width="50" height="50">
<circle
cx="25"
cy="25"
r="20"
fill="#4285F4"
/>
</svg>
`;
Применение:
new AdvancedMarkerElement({
map,
position,
content: svg
});
Advanced Markers хорошо сочетаются с современными фреймворками.
Пример DOM-компонента:
const component =
document.createElement("div");
component.innerHTML = `
<div class="marker-widget">
<span>Склад №3</span>
</div>
`;
Разметка может генерироваться:
После рендера элемент передается в content.
| Возможность | Marker | Advanced Marker |
|---|---|---|
| Пользовательский HTML | Нет | Да |
| Полноценный CSS | Нет | Да |
| SVG-контент | Ограниченно | Да |
| DOM-элементы | Нет | Да |
| Готовые PinElement | Нет | Да |
| Современная архитектура | Нет | Да |
| Гибкая кастомизация | Ограничена | Да |
| Интерактивные компоненты | Ограничены | Да |
Плохо:
<div>
<div>
<div>
<div>
Текст
</div>
</div>
</div>
</div>
Лучше:
<div>Текст</div>
Предпочтительно:
animation: pulse 1s infinite;
Вместо:
setInterval(() => {
...
}, 16);
При количестве объектов более нескольких сотен рекомендуется использовать Marker Clusterer.
Если внешний вид маркеров одинаковый, желательно использовать шаблоны и фабрики компонентов вместо создания сложной разметки вручную для каждого объекта.
Advanced Markers особенно эффективны для:
Благодаря поддержке HTML, CSS, SVG и пользовательских DOM-компонентов
класс AdvancedMarkerElement является основным инструментом
создания современных интерактивных маркеров в Google Maps JavaScript API
и предоставляет значительно более широкие возможности по сравнению с
устаревшим подходом на основе google.maps.Marker.