Mapbox GL JS строит отрисовку карты как непрерывно обновляемое состояние, где любые изменения параметров карты приводят к перерасчёту кадра. Основная идея заключается в том, что карта не «рисуется вручную», а описывается через набор свойств состояния и декларативную стилевую модель.
Ключевой принцип: любое изменение состояния карты немедленно отражается в визуальном представлении без необходимости прямого управления рендерингом.
Состояние карты включает несколько уровней:
Каждый из этих уровней связан с внутренним механизмом пересборки сцены.
Основной набор свойств карты задаёт её положение и ориентацию. Эти параметры являются реактивными: любое изменение вызывает перерасчёт матрицы проекции и перерисовку сцены.
map.setCenter([37.6173, 55.7558]);
Свойство центра определяет координату, вокруг которой строится визуализация. Изменение центра мгновенно приводит к перерасчёту тайлов, попадающих в область видимости.
map.setZoom(10);
Масштаб влияет на уровень детализации данных. При изменении zoom происходит:
map.setBearing(45);
map.setPitch(60);
Эти параметры изменяют матрицу камеры. Внутренний рендеринг пересчитывает перспективную проекцию, что делает возможным 3D-эффекты и наклоненные карты.
Стиль карты в Mapbox GL JS представляет собой JSON-структуру, которая полностью описывает визуальное представление:
Изменение стиля не является точечной операцией — это атомарная замена или дифф.
map.setStyle('mapbox://styles/mapbox/dark-v11');
При смене стиля происходит:
Это делает стиль полностью реактивным объектом: любое изменение приводит к перестроению визуальной сцены.
Отдельные свойства слоёв можно изменять без пересборки всего стиля.
map.setPaintProperty('water', 'fill-color', '#3366ff');
Изменение paint-параметров влияет на отрисовку конкретного слоя:
Эти изменения применяются в GPU-пайплайне без полной перезагрузки стиля.
map.setLayoutProperty('road-label', 'visibility', 'none');
Layout-свойства влияют на структуру слоя:
Изменения layout чаще требуют перерасчёта размещения символов.
Источники данных в Mapbox GL JS также обладают реактивной природой.
map.getSource('points').setData({
type: 'FeatureCollection',
features: []
});
Обновление данных приводит к:
Особенность заключается в том, что слой, привязанный к источнику, автоматически реагирует на изменения без дополнительной синхронизации.
Mapbox GL JS использует событийную систему, которая отражает изменения внутреннего состояния:
map.on('move', () => {});
map.on('zoom', () => {});
map.on('data', () => {});
map.on('render', () => {});
События выполняют роль триггеров реактивного обновления внешнего кода.
Ключевые категории событий:
Событие render особенно важно, так как оно вызывается на
каждом кадре при изменении состояния.
Mapbox GL JS содержит встроенный язык выражений, который позволяет описывать динамическое поведение слоёв.
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
5, 2,
10, 10
]
Размер точки изменяется в зависимости от zoom. Это декларативная реактивность: значение зависит от состояния карты.
'circle-color': [
'get',
'color'
]
Цвет вычисляется на основе свойства GeoJSON-объекта. Изменение данных автоматически изменяет визуализацию.
'line-width': [
'case',
['>', ['get', 'traffic'], 0.5],
5,
2
]
Слой реагирует на значения данных без внешнего кода.
Mapbox GL JS использует непрерывный цикл отрисовки, который активируется при изменении состояния.
Упрощённо процесс выглядит так:
Если состояние стабильно, рендеринг переходит в режим idle.
Разделение состояния на источники и слои позволяет добиться локальной реактивности.
Это предотвращает избыточные вычисления.
Карты часто используются как часть более крупного состояния приложения. Реактивная модель позволяет синхронизировать параметры карты с внешними системами.
Пример синхронизации параметров камеры:
map.on('move', () => {
const center = map.getCenter();
const zoom = map.getZoom();
});
Состояние карты становится источником истины для внешнего UI.
Реактивная модель требует контроля над частотой обновлений.
Типичные узкие места:
move и
renderОптимизация достигается через:
setPaintProperty вместо
setStylerequestAnimationFrame для синхронизации
внешних обновленийФильтры слоёв поддерживают динамическое изменение без пересборки стиля:
map.setFilter('points', ['==', ['get', 'type'], 'restaurant']);
Изменение фильтра мгновенно перерассчитывает набор отображаемых объектов.
Каждый слой можно рассматривать как функцию:
Layer = f(source, zoom, state, expressions)
Любое изменение аргументов функции приводит к пересчёту результата. Это и есть основа реактивной модели Mapbox GL JS.
Некоторые слои зависят от других через источники и визуальные параметры. Например:
Изменение одного параметра может каскадно влиять на несколько слоёв, создавая граф реактивных зависимостей внутри стиля.
Камера карты часто синхронизируется с URL-параметрами:
map.on('moveend', () => {
const center = map.getCenter();
});
Такое поведение делает состояние карты сериализуемым и восстанавливаемым.
Вместо единичных изменений состояние карты часто обновляется потоково:
Это создаёт непрерывную реактивную систему, в которой карта функционирует как живой граф состояния.