Стандартные маркеры Google Maps JavaScript API позволяют отображать значки в определённых координатах, однако во многих проектах требуется более гибкое визуальное представление: карточки объектов, ценники недвижимости, пользовательские аватары, индикаторы статусов, интерактивные кнопки и другие элементы интерфейса. Для таких задач используются маркеры с HTML-содержимым.
Современный подход основан на классе
AdvancedMarkerElement, который позволяет размещать внутри
маркера полноценные HTML-элементы и применять к ним стили CSS.
Для работы с HTML-маркерами необходимо подключить библиотеку
marker.
async function initMap() {
const { Map } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement } =
await google.maps.importLibrary("marker");
const map = new Map(document.getElementById("map"), {
center: { lat: 55.751244, lng: 37.618423 },
zoom: 12
});
}
После загрузки библиотеки становится доступен класс
AdvancedMarkerElement, поддерживающий пользовательское
содержимое.
Основная идея заключается в том, что в качестве содержимого маркера используется DOM-элемент.
const markerElement = document.createElement("div");
markerElement.textContent = "Офис";
const marker = new AdvancedMarkerElement({
map,
position: {
lat: 55.751244,
lng: 37.618423
},
content: markerElement
});
Вместо стандартной иконки на карте будет отображён HTML-элемент.
Внутри маркера может находиться произвольная структура.
const markerContent = document.createElement("div");
markerContent.innerHTML = `
<div class="custom-marker">
<div class="title">Главный офис</div>
<div class="status">Открыт</div>
</div>
`;
const marker = new AdvancedMarkerElement({
map,
position: {
lat: 55.75,
lng: 37.61
},
content: markerContent
});
Такой подход позволяет строить полноценные интерфейсные компоненты непосредственно на карте.
Внешний вид маркера обычно полностью определяется CSS.
.custom-marker {
background: white;
border-radius: 12px;
padding: 10px 14px;
box-shadow: 0 4px 12px rgba(0,0,0,0.25);
border: 1px solid #ddd;
min-width: 120px;
}
.custom-marker .title {
font-weight: bold;
margin-bottom: 4px;
}
.custom-marker .status {
color: green;
font-size: 13px;
}
Поскольку используется обычный HTML, доступны:
Фактически маркер становится полноценным веб-компонентом.
Один из самых распространённых сценариев — отображение стоимости объекта недвижимости.
const element = document.createElement("div");
element.className = "price-marker";
element.textContent = "₽ 12 500 000";
new AdvancedMarkerElement({
map,
position: {
lat: 55.76,
lng: 37.64
},
content: element
});
CSS:
.price-marker {
background: #1976d2;
color: white;
padding: 8px 14px;
border-radius: 20px;
font-weight: 600;
white-space: nowrap;
}
Подобные маркеры часто используются в сервисах поиска недвижимости и гостиниц.
HTML-маркер может содержать изображения.
const avatar = document.createElement("div");
avatar.innerHTML = `
<img
src="avatar.jpg"
alt=""
class="avatar"
>
`;
new AdvancedMarkerElement({
map,
position: {
lat: 55.73,
lng: 37.58
},
content: avatar
});
CSS:
.avatar {
width: 50px;
height: 50px;
border-radius: 50%;
border: 3px solid white;
object-fit: cover;
}
Такой формат часто применяется для отображения пользователей, водителей такси или курьеров.
Часто требуется визуально показать точку привязки маркера к координатам.
<div class="marker">
<div class="card">
Магазин
</div>
<div class="pointer"></div>
</div>
.marker {
display: flex;
flex-direction: column;
align-items: center;
}
.card {
background: white;
padding: 10px 15px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,.2);
}
.pointer {
width: 14px;
height: 14px;
background: white;
transform: rotate(45deg);
margin-top: -7px;
}
В результате создаётся визуальный эффект классического указателя местоположения.
Поскольку содержимое является DOM-элементом, к нему можно привязывать обработчики событий.
const element = document.createElement("div");
element.innerHTML = `
<button class="details-btn">
Подробнее
</button>
`;
element
.querySelector(".details-btn")
.addEventListener("click", () => {
console.log("Нажата кнопка");
});
new AdvancedMarkerElement({
map,
position: {
lat: 55.74,
lng: 37.62
},
content: element
});
Поддерживаются любые события браузера:
Это позволяет создавать интерактивные карточки объектов прямо на карте.
При большом количестве объектов удобно использовать фабрику компонентов.
function createMarkerContent(title, status) {
const element = document.createElement("div");
element.innerHTML = `
<div class="location-card">
<h4>${title}</h4>
<span>${status}</span>
</div>
`;
return element;
}
Использование:
new AdvancedMarkerElement({
map,
position: location,
content: createMarkerContent(
"Склад №1",
"Работает"
)
});
Такой подход делает код более масштабируемым.
Практически все реальные проекты получают координаты из базы данных или API.
const offices = [
{
lat: 55.75,
lng: 37.61,
title: "Офис 1"
},
{
lat: 55.77,
lng: 37.64,
title: "Офис 2"
},
{
lat: 55.73,
lng: 37.58,
title: "Офис 3"
}
];
offices.forEach(item => {
const element = document.createElement("div");
element.className = "office-marker";
element.textContent = item.title;
new AdvancedMarkerElement({
map,
position: {
lat: item.lat,
lng: item.lng
},
content: element
});
});
DOM-элемент остаётся доступным после создания маркера.
const content = document.createElement("div");
content.textContent = "Загрузка...";
const marker = new AdvancedMarkerElement({
map,
position: location,
content
});
setTimeout(() => {
content.textContent = "Данные получены";
}, 3000);
Это удобно при работе с асинхронными запросами.
Поскольку используется обычный HTML, анимация реализуется средствами CSS.
.marker-pulse {
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.15);
}
100% {
transform: scale(1);
}
}
Применение:
element.classList.add("marker-pulse");
Возможны любые CSS-анимации:
Вместо изображений можно использовать встроенный SVG.
const element = document.createElement("div");
element.innerHTML = `
<svg
width="40"
height="40"
viewBox="0 0 40 40"
>
<circle
cx="20"
cy="20"
r="18"
fill="#ff5722"
/>
</svg>
`;
Преимущества SVG:
HTML-маркер можно скрывать и показывать через стили.
content.style.display = "none";
Показ:
content.style.display = "block";
Также часто применяется управление через CSS-классы.
.hidden {
opacity: 0;
pointer-events: none;
}
content.classList.add("hidden");
События могут обрабатываться как через DOM, так и через API карты.
marker.addListener("click", () => {
console.log("Клик по маркеру");
});
Либо через элементы интерфейса внутри содержимого.
content.addEventListener("click", event => {
console.log(event.target);
});
Выбор зависит от требуемой логики приложения.
HTML-маркер может использоваться совместно с информационным окном.
const infoWindow = new google.maps.InfoWindow({
content: "<h3>Информация об объекте</h3>"
});
marker.addListener("click", () => {
infoWindow.open({
anchor: marker,
map
});
});
Такой подход позволяет показывать краткую информацию в маркере и подробную — во всплывающем окне.
HTML-маркеры значительно тяжелее стандартных иконок, поскольку каждый из них представляет отдельное DOM-дерево.
При работе с сотнями и тысячами объектов рекомендуется:
Для очень больших наборов данных стандартные маркеры или специализированные решения визуализации могут оказаться эффективнее.
function createLocationCard(data) {
const element = document.createElement("div");
element.innerHTML = `
<div class="location-card">
<div class="name">
${data.name}
</div>
<div class="address">
${data.address}
</div>
<div class="rating">
★ ${data.rating}
</div>
</div>
`;
return element;
}
new AdvancedMarkerElement({
map,
position: {
lat: 55.751244,
lng: 37.618423
},
content: createLocationCard({
name: "Кофейня",
address: "ул. Центральная, 10",
rating: 4.8
})
});
.location-card {
background: white;
padding: 12px;
border-radius: 12px;
min-width: 180px;
box-shadow: 0 4px 16px rgba(0,0,0,.15);
}
.location-card .name {
font-weight: 700;
margin-bottom: 6px;
}
.location-card .address {
font-size: 13px;
color: #666;
margin-bottom: 6px;
}
.location-card .rating {
color: #f57c00;
}
Подобная структура позволяет превращать обычные географические точки в полноценные визуальные компоненты интерфейса, отображающие сложные данные, реагирующие на действия пользователя и полностью контролируемые средствами HTML, CSS и JavaScript.