Маркер в Mapbox GL JS представляет собой объект, привязанный к
координатам на карте и отображаемый поверх слоя карты как DOM-элемент.
Базовый способ создания маркера осуществляется через конструктор
mapboxgl.Marker.
const marker = new mapboxgl.Marker()
.setLngLat([37.6173, 55.7558])
.addTo(map);
Ключевые этапы:
setLngLat;addTo.Каждый маркер является независимым объектом и может быть добавлен или удалён без влияния на карту или другие элементы.
По умолчанию используется стандартный синий маркер Mapbox. Для создания кастомного отображения применяется передача DOM-элемента в конструктор.
const el = document.createElement('div');
el.className = 'custom-marker';
const marker = new mapboxgl.Marker(el)
.setLngLat([37.6173, 55.7558])
.addTo(map);
CSS-стили позволяют полностью контролировать визуальное представление:
.custom-marker {
width: 30px;
height: 30px;
background-color: #e74c3c;
border-radius: 50%;
border: 2px solid white;
}
Кастомные маркеры используются для:
Изменение позиции маркера выполняется через setLngLat,
без необходимости пересоздания объекта.
marker.setLngLat([30.3141, 59.9386]);
Получение текущих координат:
const lngLat = marker.getLngLat();
console.log(lngLat.lng, lngLat.lat);
Такая модель позволяет динамически обновлять положение объектов, например:
Удаление выполняется методом remove:
marker.remove();
После удаления маркер полностью исключается из DOM и внутреннего состояния карты.
Типичные сценарии:
При работе с большим количеством объектов используется массив маркеров:
const markers = [];
data.forEach(item => {
const marker = new mapboxgl.Marker()
.setLngLat(item.coordinates)
.addTo(map);
markers.push(marker);
});
Очистка всех маркеров:
markers.forEach(marker => marker.remove());
markers.length = 0;
Такой подход обеспечивает централизованное управление жизненным циклом объектов.
Маркер часто используется совместно с Popup, позволяя
отображать дополнительную информацию.
const popup = new mapboxgl.Popup({ offset: 25 })
.setText('Объект на карте');
const marker = new mapboxgl.Marker()
.setLngLat([37.6173, 55.7558])
.setPopup(popup)
.addTo(map);
При клике на маркер всплывающее окно открывается автоматически.
Также возможно ручное управление:
popup.addTo(map);
popup.remove();
Маркер может быть сделан интерактивным с помощью опции
draggable.
const marker = new mapboxgl.Marker({ draggable: true })
.setLngLat([37.6173, 55.7558])
.addTo(map);
Отслеживание изменения позиции:
marker.on('dragend', () => {
const position = marker.getLngLat();
console.log(position);
});
Перетаскиваемые маркеры применяются в сценариях:
Маркер поддерживает события DOM и Mapbox API. Основные события:
marker.getElement().addEventListener('click', () => {
console.log('Клик по маркеру');
});
Также доступно использование событий карты:
map.on('click', 'layer-id', (e) => {
console.log(e.lngLat);
});
При кастомных маркерах важно учитывать, что события привязываются к
DOM-элементу, а не к объекту Marker.
В высоконагруженных приложениях критично избегать постоянного удаления и создания маркеров. Вместо этого применяется обновление состояния.
function updateMarker(marker, coordinates) {
marker.setLngLat(coordinates);
}
Для сложных UI-элементов можно обновлять содержимое DOM:
const el = marker.getElement();
el.innerHTML = `<span>${value}</span>`;
При работе с тысячами объектов стандартные маркеры становятся узким местом из-за DOM-накладных расходов.
Применяются подходы:
symbol вместо DOM-маркеров;Пример замены на слой:
map.addLayer({
id: 'points',
type: 'symbol',
source: 'points-source',
layout: {
'icon-image': 'marker-15'
}
});
Такой подход значительно повышает производительность при больших наборах данных.
В приложениях с динамическими данными маркеры часто являются отображением состояния.
Базовый паттерн обновления:
function syncMarkers(data, markers) {
markers.forEach(m => m.remove());
markers.length = 0;
data.forEach(item => {
const marker = new mapboxgl.Marker()
.setLngLat(item.coordinates)
.addTo(map);
markers.push(marker);
});
}
Более оптимизированный подход — дифференциальное обновление:
Маркер может содержать сложную структуру DOM:
const el = document.createElement('div');
el.innerHTML = `
<div class="card-marker">
<div class="title">Объект</div>
<div class="status">Активен</div>
</div>
`;
const marker = new mapboxgl.Marker(el)
.setLngLat([37.6173, 55.7558])
.addTo(map);
Это позволяет:
Управление отображением может выполняться через DOM или через добавление/удаление:
marker.getElement().style.display = 'none';
marker.getElement().style.display = 'block';
Альтернативный подход — условное удаление:
if (!shouldBeVisible) {
marker.remove();
}
В системах с фильтрацией предпочтительнее второй вариант.
Для удобства управления маркеры группируются по смысловым категориям:
const categories = {
restaurants: [],
shops: [],
transport: []
};
Добавление в категорию:
categories.restaurants.push(marker);
Очистка категории:
categories.restaurants.forEach(m => m.remove());
categories.restaurants.length = 0;
Такая структура упрощает фильтрацию и обновление данных.
Порядок отображения маркеров зависит от их DOM-позиции. Для управления слоями используется CSS:
.custom-marker {
z-index: 10;
}
Или динамическое изменение:
marker.getElement().style.zIndex = 100;
Это важно при:
Для повышения производительности маркеры могут переиспользоваться вместо пересоздания:
function moveMarker(marker, coords) {
marker.setLngLat(coords);
}
Пул объектов:
const pool = [];
function getMarker() {
return pool.pop() || new mapboxgl.Marker();
}
function releaseMarker(marker) {
marker.remove();
pool.push(marker);
}
Такой подход снижает нагрузку на DOM и ускоряет рендеринг при частых обновлениях.