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

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


Создание экземпляра карты и базовая инициализация

Жизненный цикл начинается с создания экземпляра карты:

  • инициализация WebGL-контекста
  • создание внутреннего рендер-движка
  • подготовка событийной системы
  • установка базовых параметров (центр, масштаб, стиль)

На этом этапе объект карты существует, но визуальное содержимое ещё не готово. Карта не считается полностью инициализированной до завершения загрузки стиля.

Ключевые моменты инициализации:

  • создание canvas и привязка к DOM
  • установка параметров center, zoom, bearing, pitch
  • регистрация обработчиков событий
  • запуск worker-процессов для обработки данных

Загрузка стиля и переход в состояние готовности

Следующий этап — загрузка стиля. Именно стиль определяет визуальное представление карты: источники данных, слои, фильтры, изображения, шрифты.

События жизненного цикла, связанные со стилем:

  • style.load — стиль загружен и применён
  • load — карта полностью готова к работе
  • error — ошибка загрузки ресурсов
  • styledata — изменение структуры стиля
  • sourcedata — загрузка данных источников

Карта считается функционально готовой после события load. До этого момента любые операции с слоями и источниками могут быть нестабильными или откладываться.


Внутренний рендер-цикл и постоянное обновление

После загрузки карта переходит в фазу непрерывного рендеринга. Этот цикл основан на WebGL и работает по принципу запросов кадра (requestAnimationFrame).

Основные триггеры рендера:

  • изменение центра или масштаба
  • обновление источников данных
  • добавление или удаление слоёв
  • изменение параметров стиля
  • пользовательское взаимодействие (панорамирование, вращение)

События:

  • render — каждый кадр отрисовки
  • idle — отсутствие изменений, карта «успокоилась»
  • move — изменение положения карты
  • zoom — изменение масштаба
  • rotate — вращение

Состояние idle особенно важно для оптимизации: оно сигнализирует, что карта завершила все активные обновления и может быть использована для тяжёлых операций (например, снимков или аналитики).


Управление источниками данных

Источники данных (sources) являются динамической частью жизненного цикла карты. Они могут добавляться, обновляться и удаляться в любой момент после загрузки стиля.

Этапы работы источника:

  • регистрация источника через addSource
  • загрузка данных (vector tiles, GeoJSON, raster tiles)
  • обработка данных в worker-потоках
  • передача в рендер-движок

События:

  • sourcedata — обновление данных источника
  • data — завершение загрузки данных
  • dataloading — начало загрузки данных

Особое внимание требуется при динамических источниках:

  • частые обновления GeoJSON могут перегружать main thread
  • tile-based источники оптимальнее для больших объёмов данных
  • необходимо учитывать кэширование и повторное использование тайлов

Жизненный цикл слоёв

Слои (layers) — визуальная часть карты, зависящая от источников. Их жизненный цикл тесно связан со стилем.

Основные операции:

  • добавление слоя (addLayer)
  • изменение порядка (moveLayer)
  • обновление свойств (setPaintProperty, setLayoutProperty)
  • удаление (removeLayer)

Слой проходит несколько внутренних стадий:

  1. регистрация в стиле
  2. привязка к источнику
  3. компиляция рендер-шейдеров
  4. участие в отрисовке кадров

Ошибки жизненного цикла слоёв часто возникают при:

  • удалении источника до удаления слоя
  • изменении стиля без учёта зависимостей
  • конфликте идентификаторов слоёв

Изменение стиля и пересборка состояния

Метод setStyle запускает один из самых сложных сценариев жизненного цикла.

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

  • полная очистка текущего графа слоёв и источников
  • сброс WebGL-состояния
  • загрузка нового JSON-стиля
  • повторная инициализация ресурсов

События:

  • styledata — промежуточные изменения структуры
  • style.load — завершение загрузки нового стиля

Важно учитывать:

  • асинхронность пересборки
  • временную недоступность слоёв
  • необходимость повторной регистрации кастомных источников

Работа с ресурсами: изображения и шрифты

Ресурсы карты также имеют собственный жизненный цикл:

  • загрузка sprite-атласа
  • кэширование glyph-ов
  • динамическая подгрузка изображений

Событие:

  • styleimagemissing — отсутствие изображения в стиле

При этом:

  • sprite и glyph cache управляются внутренним рендерером
  • повторное использование ресурсов критично для производительности
  • очистка кеша происходит при смене стиля

Взаимодействие с пользовательскими событиями

Жизненный цикл карты тесно связан с пользовательским вводом.

Основные события:

  • mousedown, mousemove, mouseup
  • touchstart, touchmove, touchend
  • click, dblclick
  • wheel (zoom)

Эти события влияют на:

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

При высокой частоте взаимодействия важно учитывать:

  • throttling событий
  • оптимизацию обработчиков
  • минимизацию синхронных вычислений

Интеграция с фреймворками и монтаж/размонтаж

В SPA-приложениях жизненный цикл карты должен быть синхронизирован с жизненным циклом компонента.

Типичный сценарий:

  • создание карты при mount
  • привязка к DOM-элементу
  • подписка на события
  • уничтожение при unmount

Критические моменты:

  • карта продолжает рендерить даже без видимости контейнера
  • необходимо вручную вызывать remove
  • утечки возникают при сохранении ссылок на события

Правильное завершение жизненного цикла включает:

  • удаление всех listeners
  • вызов map.remove()
  • освобождение WebGL-контекста

Завершение работы и освобождение ресурсов

Метод remove завершает жизненный цикл карты.

Происходит:

  • остановка render loop
  • удаление canvas из DOM
  • освобождение WebGL ресурсов
  • очистка внутренних структур

Без корректного вызова удаления возможны:

  • утечки памяти GPU
  • зависание WebGL-контекста
  • накопление неиспользуемых worker-ов

Особенности повторного использования экземпляра

Экземпляр карты не предназначен для повторной инициализации после удаления. Вместо этого используется создание нового объекта.

Попытки повторного использования приводят к:

  • неконсистентному состоянию стиля
  • конфликтам WebGL-контекста
  • ошибкам рендеринга

Управление состоянием в реальном времени

Во время активной работы карта постоянно изменяет внутреннее состояние:

  • камера (camera state)
  • буферы рендеринга
  • состояние слоёв
  • кэш тайлов

Это состояние неявно синхронизируется между:

  • main thread
  • Web Worker
  • GPU pipeline

Любое вмешательство должно учитывать асинхронность обновлений и возможные race conditions между событиями render, data и idle.