В MapLibre GL JS маркер представляет собой DOM-элемент, привязанный к
координатам карты и перемещающийся вместе с ней при масштабировании и
панорамировании. Базовая сущность Marker используется для
отображения точек интереса, пользовательских объектов и интерактивных
элементов интерфейса.
Создание маркера начинается с инстанцирования объекта:
import maplibregl from "maplibre-gl";
const marker = new maplibregl.Marker()
.setLngLat([30.315868, 59.939095])
.addTo(map);
По умолчанию используется стандартный SVG-элемент в виде синего пина. Однако визуальная настройка маркера в MapLibre GL JS может быть значительно расширена за счёт параметров конструктора и использования кастомных DOM-элементов.
Встроенный маркер поддерживает ограниченную настройку внешнего вида через параметры конструктора:
const marker = new maplibregl.Marker({
color: "#ff0000"
})
.setLngLat([30.3, 59.9])
.addTo(map);
Параметр color изменяет основной цвет SVG-маркера. Это
быстрый способ визуально различать категории объектов без создания
кастомного элемента.
Дополнительно используются:
rotation: угол поворота маркера в градусахscale: масштабирование (в некоторых реализациях через
CSS)anchor: точка привязки (например,
"center", "bottom")offset: смещение относительно координатыПример:
const marker = new maplibregl.Marker({
color: "#2ecc71",
rotation: 45,
anchor: "bottom",
offset: [0, -10]
})
.setLngLat([30.32, 59.93])
.addTo(map);
Гибкость системы маркеров достигается через передачу DOM-элемента в
конструктор Marker. Это позволяет полностью контролировать
внешний вид: от простых иконок до сложных интерактивных компонентов.
const el = document.createElement("div");
el.className = "custom-marker";
el.innerHTML = `<div class="dot"></div>`;
const marker = new maplibregl.Marker(el)
.setLngLat([30.31, 59.94])
.addTo(map);
CSS-оформление:
.custom-marker {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.custom-marker .dot {
width: 14px;
height: 14px;
background: #e74c3c;
border-radius: 50%;
box-shadow: 0 0 6px rgba(0,0,0,0.3);
}
Такой подход позволяет реализовать:
Вместо HTML-разметки можно использовать <img> как
основу маркера:
const img = document.createElement("img");
img.src = "/icons/location.png";
img.style.width = "32px";
img.style.height = "32px";
const marker = new maplibregl.Marker(img)
.setLngLat([30.33, 59.92])
.addTo(map);
Преимущество такого подхода — простота и высокая производительность по сравнению с многослойными DOM-структурами.
Визуальное положение маркера относительно координаты на карте
определяется параметром anchor. Он задаёт, какая точка
элемента считается «географической привязкой».
Основные значения:
centertopbottomleftrighttop-left, bottom-right)Пример:
new maplibregl.Marker({
anchor: "bottom"
})
.setLngLat([30.30, 59.93])
.addTo(map);
Использование правильного якоря критично при работе с кастомными иконками, иначе визуальное смещение приводит к неточной привязке к координатам.
Параметр offset позволяет корректировать положение
маркера в пикселях:
new maplibregl.Marker({
offset: [10, -20]
})
.setLngLat([30.31, 59.94])
.addTo(map);
Смещение особенно полезно при:
DOM-маркеры в MapLibre GL JS сохраняют размер в пикселях, что означает отсутствие автоматической географической масштабируемости. Это может быть как преимуществом (стабильная визуализация), так и ограничением.
Для динамического изменения внешнего вида используется обработка
события zoom:
map.on("zoom", () => {
const zoom = map.getZoom();
const scale = Math.max(0.5, Math.min(2, zoom / 10));
document.querySelectorAll(".custom-marker").forEach(el => {
el.style.transform = `scale(${scale})`;
});
});
Такой подход позволяет:
HTML-маркеры могут реагировать на состояние данных через CSS-классы:
el.classList.add("active");
CSS:
.custom-marker.active {
background: #27ae60;
transform: scale(1.2);
}
.custom-marker.inactive {
background: #7f8c8d;
opacity: 0.6;
}
Это позволяет реализовывать:
В MapLibre GL JS существует два основных подхода к отображению точек:
Marker)SymbolLayer с источником
GeoJSONDOM-маркеры обеспечивают максимальную гибкость внешнего вида, но создают нагрузку на DOM при большом количестве объектов.
Сравнение:
DOM Marker:
Symbol Layer:
Для большого количества точек предпочтительнее использовать слои:
map.addSource("points", {
type: "geojson",
data: geojsonData
});
map.addLayer({
id: "points-layer",
type: "symbol",
source: "points",
layout: {
"icon-image": "marker-icon",
"icon-size": 1
}
});
DOM-маркеры поддерживают стандартные события браузера:
el.addEventListener("click", () => {
el.classList.toggle("active");
});
Также доступна интеграция с картой:
marker.getElement().addEventListener("mouseenter", () => {
marker.getElement().style.cursor = "pointer";
});
Это используется для:
Кастомные маркеры могут включать несколько слоёв:
el.innerHTML = `
<div class="marker-wrapper">
<div class="pulse"></div>
<div class="core"></div>
</div>
`;
CSS-анимация:
.pulse {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(231, 76, 60, 0.3);
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { transform: scale(0.8); opacity: 1; }
100% { transform: scale(1.5); opacity: 0; }
}
Такая структура позволяет создавать визуально насыщенные индикаторы без сторонних библиотек.
DOM-маркеры рендерятся поверх WebGL-слоя карты, что создаёт архитектурное разделение:
Это приводит к следующим особенностям:
По этой причине архитектура приложений часто комбинирует оба подхода: слои для массовых данных и DOM-маркеры для ключевых объектов интерфейса