Marker класс

Marker представляет собой базовый интерактивный объект для размещения DOM-элемента на карте в координатах долготы и широты. В MapLibre GL JS маркеры используются для обозначения точек интереса, пользовательских объектов, динамических данных и интерактивных элементов интерфейса поверх векторной карты.

Marker не является частью WebGL-рендеринга. Он создаётся как HTML-элемент, позиционируемый поверх карты, и синхронизируется с её трансформациями (pan, zoom, rotate). Это обеспечивает гибкость визуализации и возможность использования произвольной разметки и стилей.

Базовая инициализация Marker

Создание маркера выполняется через конструктор maplibregl.Marker:

const marker = new maplibregl.Marker();
marker.setLngLat([30.5, 50.5]).addTo(map);

Ключевые этапы:

  • создание экземпляра Marker
  • установка координат через setLngLat
  • добавление на карту через addTo

Marker не отображается до момента привязки к экземпляру карты.

Конструктор и параметры конфигурации

Конструктор Marker принимает объект настроек, определяющий поведение и внешний вид:

const marker = new maplibregl.Marker({
  color: "#ff0000",
  draggable: true,
  anchor: "bottom",
  offset: [0, -10]
});

Основные параметры:

  • color — цвет стандартного маркера (если используется дефолтный элемент)
  • draggable — включение перетаскивания
  • anchor — точка привязки элемента к координате
  • offset — смещение в пикселях относительно якоря
  • element — пользовательский DOM-элемент

Использование пользовательского элемента

Marker поддерживает полную замену стандартного DOM-элемента:

const el = document.createElement("div");
el.className = "custom-marker";
el.style.width = "20px";
el.style.height = "20px";
el.style.background = "blue";
el.style.borderRadius = "50%";

const marker = new maplibregl.Marker({
  element: el
})
.setLngLat([30.5, 50.5])
.addTo(map);

Пользовательский элемент позволяет:

  • внедрять SVG-иконки
  • использовать HTML-разметку
  • добавлять анимации CSS
  • интегрировать состояния приложения

Привязка к координатам

Метод setLngLat определяет географическое положение маркера:

marker.setLngLat([longitude, latitude]);

Формат координат строго фиксирован:

  • первый элемент — долгота
  • второй элемент — широта

Marker автоматически пересчитывает экранные координаты при изменении состояния карты.

Получение текущего положения:

const lngLat = marker.getLngLat();

Результат возвращает объект:

{ lng: number, lat: number }

Добавление и удаление с карты

Добавление маркера:

marker.addTo(map);

Удаление маркера:

marker.remove();

Повторное добавление после удаления возможно без пересоздания экземпляра.

Перетаскиваемые маркеры

При включении draggable: true активируется возможность изменения координат пользователем:

const marker = new maplibregl.Marker({
  draggable: true
})
.setLngLat([30.5, 50.5])
.addTo(map);

Перетаскивание сопровождается событиями:

marker.on("dragstart", () => {});
marker.on("drag", () => {});
marker.on("dragend", () => {});

После завершения перетаскивания координаты можно получить через getLngLat.

События Marker

Marker поддерживает событийную модель:

  • click
  • dragstart
  • drag
  • dragend
  • mousedown
  • mouseup

Пример обработки:

marker.on("click", (e) => {
  console.log("Marker clicked");
});

События проксируются через DOM-слой маркера.

Привязка всплывающих окон (Popup)

Marker может быть связан с Popup:

const popup = new maplibregl.Popup()
  .setText("Информация об объекте");

marker.setPopup(popup);

При клике на маркер Popup открывается автоматически.

Получение привязанного Popup:

const popup = marker.getPopup();

Управление DOM-элементом маркера

Метод getElement возвращает DOM-ноду:

const el = marker.getElement();
el.style.border = "2px solid red";

Это позволяет динамически изменять внешний вид маркера после его создания.

Anchor и позиционирование

Anchor определяет точку привязки элемента относительно координаты:

  • center
  • top
  • bottom
  • left
  • right
  • комбинации углов (top-left, bottom-right)

Пример:

new maplibregl.Marker({
  anchor: "bottom"
});

При изменении anchor смещается точка привязки, что влияет на визуальное положение относительно координаты.

Offset и тонкая настройка позиционирования

Offset используется для пиксельной корректировки:

new maplibregl.Marker({
  offset: [10, -20]
});

Первое значение — смещение по X, второе — по Y.

Применяется для:

  • компенсации размеров иконок
  • визуального выравнивания
  • предотвращения перекрытий

Производительность Marker

Marker создаёт отдельные DOM-узлы для каждого экземпляра. При большом количестве объектов возможны ограничения производительности:

  • деградация при тысячах DOM-элементов
  • повышенная нагрузка на layout и paint
  • необходимость кластеризации или замены на layer-based визуализацию

Для больших наборов данных часто используется символический слой (SymbolLayer) вместо Marker.

Сравнение Marker и Layer-based подхода

Marker:

  • HTML/DOM
  • высокая гибкость визуализации
  • низкая производительность на больших объёмах
  • подходит для интерактивных объектов

Layer (SymbolLayer):

  • WebGL-рендеринг
  • высокая производительность
  • ограниченная кастомизация
  • подходит для массовых данных

Жизненный цикл Marker

Типичный жизненный цикл включает:

  1. создание экземпляра
  2. конфигурация параметров
  3. установка координат
  4. добавление на карту
  5. взаимодействие (события, перемещения)
  6. удаление или повторное использование

Marker сохраняет состояние независимо от карты до явного удаления.

Динамическое обновление позиции

Положение может изменяться в реальном времени:

setInterval(() => {
  const lng = 30 + Math.random();
  const lat = 50 + Math.random();
  marker.setLngLat([lng, lat]);
}, 1000);

MapLibre автоматически пересчитывает экранное положение без пересоздания DOM.

Интеграция с внешними данными

Marker часто используется для отображения данных из API:

  • геолокационные сервисы
  • трекинг объектов
  • события в реальном времени
  • пользовательские точки интереса

Обновление маркеров обычно синхронизируется с потоками данных через setLngLat и изменение DOM-элемента.

Особенности работы с несколькими маркерами

При большом количестве маркеров применяется управление коллекциями:

const markers = [];

data.forEach(point => {
  const marker = new maplibregl.Marker()
    .setLngLat(point.coords)
    .addTo(map);

  markers.push(marker);
});

Для очистки:

markers.forEach(m => m.remove());

Управление массивами маркеров требует контроля жизненного цикла объектов для предотвращения утечек памяти.