MapLibre GL JS предоставляет API для добавления интерактивных
объектов поверх векторной карты. Маркеры в этой библиотеке реализуются
как DOM-элементы, привязанные к координатам долготы и широты, и
управляются через класс Marker.
Перед созданием маркеров требуется инициализировать карту и задать
стиль отображения. Основной объект создаётся через Map,
который управляет рендерингом WebGL-сцены и слоями.
import maplibregl from 'maplibre-gl';
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [69.2401, 41.2995],
zoom: 10
});
Параметр container указывает DOM-элемент, внутри
которого будет размещена карта. style определяет визуальную
модель данных. center задаёт начальную позицию камеры, а
zoom — масштаб.
Маркеры создаются через конструктор maplibregl.Marker.
Минимальная конфигурация предполагает только указание координат.
const marker = new maplibregl.Marker()
.setLngLat([69.2401, 41.2995])
.addTo(map);
Метод setLngLat принимает массив
[longitude, latitude]. Важно учитывать порядок координат:
сначала долгота, затем широта, что соответствует географическому
стандарту GeoJSON.
Метод addTo(map) привязывает маркер к конкретному
экземпляру карты.
Каждый маркер в MapLibre GL JS представляет собой HTML-элемент,
который позиционируется через трансформации CSS. По умолчанию
используется элемент div с классом
maplibregl-marker.
Это означает:
Для изменения внешнего вида можно передать HTML-элемент в конструктор
Marker.
const el = document.createElement('div');
el.className = 'custom-marker';
el.style.width = '20px';
el.style.height = '20px';
el.style.backgroundColor = 'red';
el.style.borderRadius = '50%';
const marker = new maplibregl.Marker({ element: el })
.setLngLat([69.2401, 41.2995])
.addTo(map);
CSS-класс позволяет централизованно управлять стилями:
.custom-marker {
border: 2px solid white;
box-shadow: 0 0 6px rgba(0,0,0,0.5);
}
Использование кастомного элемента даёт полный контроль над визуальным представлением, включая SVG, Canvas или сложные HTML-компоненты.
Маркеры часто используются совместно с всплывающими окнами. Класс
Popup привязывается к маркеру через метод
setPopup.
const popup = new maplibregl.Popup({ offset: 25 })
.setHTML('<strong>Точка интереса</strong><p>Описание объекта</p>');
const marker = new maplibregl.Marker()
.setLngLat([69.2401, 41.2995])
.setPopup(popup)
.addTo(map);
При клике на маркер popup автоматически открывается, а его позиция синхронизируется с координатами.
MapLibre GL JS поддерживает интерактивное перемещение маркеров с
помощью опции draggable.
const marker = new maplibregl.Marker({ draggable: true })
.setLngLat([69.2401, 41.2995])
.addTo(map);
Обработка события изменения позиции:
marker.on('dragend', () => {
const lngLat = marker.getLngLat();
console.log(lngLat.lng, lngLat.lat);
});
Метод getLngLat() возвращает текущие координаты маркера
после завершения перетаскивания.
При работе с набором объектов обычно используется массив координат и цикл создания маркеров.
const points = [
[69.2401, 41.2995],
[69.2500, 41.3100],
[69.2600, 41.3200]
];
points.forEach(coords => {
new maplibregl.Marker()
.setLngLat(coords)
.addTo(map);
});
Такая структура позволяет масштабировать отображение точек без изменения логики карты.
DOM-маркеры плохо масштабируются при тысячах объектов. В таких случаях используется подход:
GeoJSONSource и символические слои
(symbol layer);Пример перехода к источнику данных:
map.on('load', () => {
map.addSource('points', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [69.2401, 41.2995]
}
}
]
}
});
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points',
paint: {
'circle-radius': 6,
'circle-color': '#ff0000'
}
});
});
Этот подход исключает использование DOM и переносит рендеринг в WebGL.
Маркер можно динамически перемещать без пересоздания:
marker.setLngLat([69.3000, 41.3300]);
Обновление позиции мгновенно отражается на карте без дополнительных вычислений.
В прикладных сценариях маркеры часто используются как представление состояния данных:
Пример обновления из внешнего источника:
function updateMarkerPosition(data) {
marker.setLngLat([data.lng, data.lat]);
}
Такой подход позволяет интегрировать карту в реактивные интерфейсы и системы отслеживания объектов.
По умолчанию точка привязки маркера находится в центре элемента. Её
можно изменить через anchor.
new maplibregl.Marker({ anchor: 'bottom' })
.setLngLat([69.2401, 41.2995])
.addTo(map);
Доступные значения:
centertopbottomleftrighttop-leftВыбор якоря критичен при использовании иконок с чёткой геометрией.
Маркер может участвовать в событийной модели:
marker.getElement().addEventListener('click', () => {
console.log('Маркер активирован');
});
Такой подход даёт возможность реализовать кастомное поведение без привязки к popup-механике.
Использование Marker оправдано при:
При увеличении количества объектов растёт нагрузка на:
Поэтому архитектурно важно разделять: