Popup класс

Класс Popup в MapLibre GL JS представляет собой инструмент для отображения всплывающих информационных окон, привязанных к координатам карты или к экранным событиям. Popup используется для отображения краткой информации о геообъектах, точках интереса, результатах взаимодействия с картой и динамически формируемых данных.

Popup строится поверх карты в отдельном DOM-слое и синхронизируется с координатами через проекцию географических значений в экранные пиксели.


Создание Popup и базовая инициализация

Экземпляр Popup создаётся через конструктор:

import maplibregl from "maplibre-gl";

const popup = new maplibregl.Popup();

При создании можно передать объект конфигурации, определяющий поведение и внешний вид всплывающего окна:

const popup = new maplibregl.Popup({
  closeButton: true,
  closeOnClick: true,
  closeOnMove: false,
  offset: 10,
  maxWidth: "300px",
  className: "custom-popup"
});

Параметры конструктора Popup

closeButton Управляет отображением кнопки закрытия.

  • true — кнопка отображается
  • false — скрыта

closeOnClick Определяет закрытие popup при клике по карте.

  • true — закрывается при любом клике по карте
  • false — остаётся открытым

closeOnMove Закрывает popup при изменении положения карты (pan, zoom, rotate).

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

offset Смещение popup относительно точки привязки.

Поддерживает:

  • число (единое смещение)
  • объект смещений по направлениям:
offset: {
  top: [0, 10],
  bottom: [0, -10],
  left: [10, 0],
  right: [-10, 0]
}

maxWidth Ограничивает ширину контейнера popup.

maxWidth: "240px"

className Добавляет пользовательский CSS-класс к корневому элементу popup.


Привязка Popup к карте

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

popup
  .setLngLat([37.6173, 55.7558])
  .setHTML("<strong>Москва</strong>")
  .addTo(map);

Метод addTo(map) регистрирует popup в DOM карты и запускает его рендеринг.


Методы управления содержимым

setLngLat

Определяет географическую позицию popup:

popup.setLngLat([longitude, latitude]);

При изменении координат popup автоматически пересчитывает позицию на экране.


setHTML

Устанавливает HTML-содержимое:

popup.setHTML(`
  <div>
    <h3>Объект</h3>
    <p>Описание точки интереса</p>
  </div>
`);

HTML вставляется напрямую в DOM без дополнительной обработки, что требует контроля за безопасностью данных.


setText

Устанавливает текстовое содержимое без HTML-разметки:

popup.setText("Простой текстовый заголовок");

Используется для безопасного вывода данных.


setDOMContent

Позволяет передать готовый DOM-элемент:

const container = document.createElement("div");
container.innerHTML = "<b>Динамический блок</b>";

popup.setDOMContent(container);

Подходит для сложной логики рендера, включая интеграцию с фреймворками.


Управление жизненным циклом Popup

addTo

Добавляет popup на карту:

popup.addTo(map);

Без вызова addTo popup остаётся неактивным.


remove

Удаляет popup из карты:

popup.remove();

Используется при ручном управлении состоянием или очистке интерфейса.


isOpen

Проверка состояния:

popup.isOpen();

Возвращает true, если popup отображается.


Привязка к маркерам

Popup часто используется совместно с маркерами:

const marker = new maplibregl.Marker()
  .setLngLat([37.6173, 55.7558])
  .setPopup(
    new maplibregl.Popup().setText("Маркер в Москве")
  )
  .addTo(map);

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


Поведение при взаимодействии с картой

Popup реагирует на события карты через внутреннюю систему пересчёта координат:

  • zoom → перерасчёт позиции пикселя
  • drag → синхронное смещение
  • rotate → переориентация относительно viewport

При включённом closeOnMove любое движение карты приводит к удалению popup.


Позиционирование и anchor

Popup автоматически выбирает положение относительно точки, но может быть явно задано:

const popup = new maplibregl.Popup({
  anchor: "top"
});

Возможные значения anchor:

  • top
  • bottom
  • left
  • right
  • top-left
  • top-right
  • bottom-left
  • bottom-right

Anchor влияет на направление «хвоста» popup и его смещение.


Offset и точная настройка положения

Offset играет ключевую роль в UX при плотных интерфейсах.

Пример комбинированной настройки:

const popup = new maplibregl.Popup({
  offset: {
    bottom: [0, -20],
    top: [0, 20]
  }
});

Такая конфигурация позволяет избегать перекрытия маркеров и UI-элементов карты.


Динамическое обновление содержимого

Popup можно обновлять без пересоздания:

popup.setHTML(`<div>Загрузка...</div>`);

fetch("/api/info")
  .then(res => res.json())
  .then(data => {
    popup.setHTML(`<div>${data.title}</div>`);
  });

Этот подход применяется для асинхронных данных и API-интеграций.


Использование событий DOM внутри Popup

Так как содержимое popup — это DOM, возможна регистрация событий:

popup.setHTML(`
  <button id="btn">Нажать</button>
`);

document.addEventListener("click", (e) => {
  if (e.target && e.target.id === "btn") {
    console.log("Клик внутри popup");
  }
});

В более строгих архитектурах обработчики привязываются через setDOMContent.


Поведение при множественных Popup

MapLibre GL JS не ограничивает количество popup, однако:

  • каждый popup создаёт отдельный DOM-слой
  • большое количество одновременно открытых popup снижает производительность
  • рекомендуется использовать один активный popup и переиспользовать его

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

const popup = new maplibregl.Popup();

map.on("click", (e) => {
  popup
    .setLngLat(e.lngLat)
    .setHTML("Данные точки")
    .addTo(map);
});

Стилизация Popup

Popup имеет стандартную структуру DOM:

  • .maplibregl-popup
  • .maplibregl-popup-content
  • .maplibregl-popup-tip
  • .maplibregl-popup-close-button

Переопределение стилей:

.maplibregl-popup-content {
  background: #1e1e1e;
  color: white;
  border-radius: 6px;
}

.maplibregl-popup-tip {
  border-top-color: #1e1e1e;
}

Производительность и оптимизация

Popup влияет на производительность через:

  • DOM-операции
  • пересчёт позиции при каждом событии карты
  • обработку событий внутри содержимого

Оптимизационные практики:

  • избегать тяжёлого HTML внутри popup
  • ограничивать число одновременно открытых окон
  • использовать setText вместо setHTML для простых случаев
  • переиспользовать экземпляры Popup

Типовые сценарии применения

  • отображение информации о точках интереса
  • вывод результатов поиска по карте
  • интерактивные подсказки при клике
  • отображение состояния геообъектов
  • динамические данные API (погода, статистика, трекинг)

Поведение при уничтожении карты

При вызове:

map.remove();

все связанные popup автоматически удаляются, включая DOM-узлы и обработчики событий, что предотвращает утечки памяти.