MapLibre GL JS предоставляет механизм маркеров как надслой над картой, позволяющий отображать произвольные DOM-элементы или стандартные визуальные указатели в координатах географической сцены. В отличие от источников данных и слоёв, маркеры существуют в DOM-дереве и не участвуют в WebGL-рендеринге, что делает их гибкими, но менее производительными при большом количестве объектов.
Основной класс для работы с маркерами —
maplibregl.Marker. Он принимает HTML-элемент или создаёт
стандартный маркер по умолчанию.
import maplibregl from "maplibre-gl";
const map = new maplibregl.Map({
container: "map",
style: "https://demotiles.maplibre.org/style.json",
center: [37.6173, 55.7558],
zoom: 10
});
const marker = new maplibregl.Marker()
.setLngLat([37.6173, 55.7558])
.addTo(map);
Маркер создаётся как независимый объект и привязывается к карте
методом addTo. Координаты задаются в формате
[longitude, latitude].
Маркер может быть полностью переопределён через DOM-элемент, что позволяет реализовать сложную визуализацию.
const el = document.createElement("div");
el.className = "custom-marker";
el.innerHTML = `<div class="pin"></div>`;
const marker = new maplibregl.Marker({
element: el,
anchor: "bottom"
})
.setLngLat([37.6173, 55.7558])
.addTo(map);
Кастомные маркеры позволяют внедрять иконки, аватары, индикаторы состояния и анимации. При этом каждый такой элемент становится частью DOM, что влияет на производительность при массовом использовании.
Маркер можно перемещать без пересоздания объекта:
marker.setLngLat([37.62, 55.76]);
Обновление координат происходит мгновенно, карта автоматически пересчитывает позицию элемента в экранных координатах.
Маркер часто используется вместе с всплывающими окнами
Popup.
const popup = new maplibregl.Popup({ offset: 25 })
.setText("Точка интереса");
marker.setPopup(popup);
Popup активируется по клику на маркер и автоматически привязывается к его позиции. Это создаёт связку «объект — описание».
Несколько маркеров создаются как независимые экземпляры:
const points = [
[37.61, 55.75],
[37.62, 55.76],
[37.63, 55.74]
];
points.forEach(coord => {
new maplibregl.Marker()
.setLngLat(coord)
.addTo(map);
});
При большом количестве объектов такой подход становится ресурсоёмким, поскольку каждый маркер — отдельный DOM-узел.
Для последующего управления маркерами необходимо сохранять их в структуре данных:
const markers = [];
const marker = new maplibregl.Marker()
.setLngLat([37.6, 55.75])
.addTo(map);
markers.push(marker);
Такой подход позволяет централизованно удалять или обновлять объекты.
Удаление выполняется методом remove, который отсоединяет
маркер от карты и DOM.
marker.remove();
После вызова объект перестаёт отображаться, а связанные DOM-узлы уничтожаются.
При управлении коллекцией маркеров применяется массовое удаление:
markers.forEach(m => m.remove());
markers.length = 0;
Вместо удаления можно управлять видимостью через DOM-стили:
marker.getElement().style.display = "none";
или
marker.getElement().style.visibility = "hidden";
Такой подход сохраняет объект в памяти, но исключает его визуализацию.
Маркер может быть сделан интерактивным с помощью опции
draggable.
const marker = new maplibregl.Marker({ draggable: true })
.setLngLat([37.61, 55.75])
.addTo(map);
marker.on("dragend", () => {
const lngLat = marker.getLngLat();
});
Перетаскивание полезно для редактирования координат или пользовательского выбора точки.
Маркер проходит несколько этапов:
MarkersetLngLataddToremoveКаждый этап влияет на состояние DOM и внутренние слушатели событий.
При динамических данных маркеры часто пересоздаются или обновляются:
function updateMarker(marker, data) {
marker.setLngLat([data.lng, data.lat]);
}
или пересоздаются полностью при изменении набора данных.
Маркер не является частью WebGL-слоя. В отличие от
GeoJSON source + layer, маркеры:
Для сотен и тысяч объектов предпочтительнее слои, а не маркеры.
При работе с динамическими интерфейсами важно полностью освобождать ресурсы:
map.on("remove", () => {
markers.forEach(m => m.remove());
});
Удаление карты без очистки маркеров может привести к утечкам памяти из-за оставшихся DOM-узлов и обработчиков событий.
Маркер поддерживает стандартные DOM-события:
marker.getElement().addEventListener("click", () => {
console.log("Маркер нажат");
});
Также доступны события перетаскивания и взаимодействия с картой.
При сложных интерфейсах маркеры часто инкапсулируются в отдельные менеджеры:
class MarkerManager {
constructor(map) {
this.map = map;
this.markers = [];
}
add(coord) {
const marker = new maplibregl.Marker()
.setLngLat(coord)
.addTo(this.map);
this.markers.push(marker);
return marker;
}
clear() {
this.markers.forEach(m => m.remove());
this.markers = [];
}
}
Такой подход упрощает контроль над жизненным циклом объектов и предотвращает накопление неиспользуемых маркеров.