Работа с динамическими изменениями состояния карты в Mapbox GL JS строится вокруг нескольких механизмов: переходов (transitions), анимаций камеры, выражений (expressions), обновления стилей и источников данных, а также ручного управления через цикл анимации. Совокупность этих инструментов позволяет создавать плавные визуальные эффекты, синхронизированные с временем, пользовательским вводом или внешними данными.
Каждое визуальное свойство слоя в Mapbox GL JS поддерживает
встроенную анимацию перехода. Это относится к
paint-свойствам, таким как цвет, прозрачность, ширина
линий, радиус кругов и другие параметры визуализации.
Ключевой механизм — объект transition, задающий
длительность и задержку изменения.
map.setPaintProperty('cities-layer', 'circle-radius', 8);
map.setPaintProperty('cities-layer', 'circle-radius-transition', {
duration: 1200,
delay: 0
});
map.setPaintProperty('cities-layer', 'circle-radius', 20);
В этом примере изменение радиуса круга происходит плавно, а не мгновенно.
duration — длительность перехода в миллисекундахdelay — задержка перед началом анимацииВажно, что transition применяется только к изменяющимся значениям. Повторное присвоение того же значения не вызывает анимацию.
Метод setPaintProperty используется для динамического
обновления визуальных параметров слоя во времени. Он часто применяется в
сочетании с таймерами или анимационными циклами.
let opacity = 1;
setInterval(() => {
opacity -= 0.05;
if (opacity < 0) opacity = 1;
map.setPaintProperty('water-layer', 'fill-opacity', opacity);
}, 100);
Подобный подход позволяет создавать эффекты пульсации, мигания или затухания.
Для более точного управления временем применяется
requestAnimationFrame, который синхронизируется с частотой
обновления экрана.
let start = performance.now();
function animate(timestamp) {
const progress = (timestamp - start) / 2000; // 2 секунды цикл
const value = Math.sin(progress * Math.PI * 2) * 0.5 + 0.5;
map.setPaintProperty('pulse-layer', 'circle-opacity', value);
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Этот подход позволяет создавать непрерывные анимации без рывков и лишней нагрузки.
Изменение свойств карты включает не только стили, но и параметры
камеры: центр, масштаб, наклон и поворот. Для этого используются методы
easeTo, flyTo, jumpTo.
map.easeTo({
center: [30.3, 59.9],
zoom: 10,
duration: 3000
});
easeTo — плавное движение с контролем скоростиflyTo — имитация полёта с дуговой траекториейjumpTo — мгновенное изменение без анимацииКомбинация камерных анимаций и изменений слоёв позволяет синхронизировать визуальные эффекты во времени.
Expressions позволяют изменять свойства в зависимости от данных или масштаба, включая временные зависимости.
map.setPaintProperty('temperature-layer', 'circle-color', [
'interpolate',
['linear'],
['get', 'temp'],
0, '#2c7bb6',
10, '#abd9e9',
20, '#ffffbf',
30, '#fdae61',
40, '#d7191c'
]);
Хотя здесь нет явного времени, такие выражения часто комбинируются с обновлением данных во времени, создавая динамическую карту.
Изменение свойств часто связано с обновлением GeoJSON-источников.
setInterval(() => {
const source = map.getSource('points');
const updatedData = generateNewGeoJSON();
source.setData(updatedData);
}, 5000);
Каждое обновление источника автоматически приводит к перерасчёту слоёв, что создаёт эффект движения объектов во времени.
Изменение геометрии — один из наиболее выразительных способов временной анимации.
let t = 0;
function animate() {
t += 0.01;
const lng = 30 + Math.cos(t) * 0.5;
const lat = 50 + Math.sin(t) * 0.5;
const source = map.getSource('moving-point');
source.setData({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [lng, lat]
}
});
requestAnimationFrame(animate);
}
animate();
Такой подход используется для отображения движущихся объектов: транспорта, потоков, сигналов.
Тепловые карты часто используются для визуализации изменений плотности во времени.
map.setPaintProperty('heatmap-layer', 'heatmap-intensity', [
'interpolate',
['linear'],
['zoom'],
0, 1,
9, 3
]);
При обновлении данных по временным срезам создаётся эффект «пульсации» плотности.
При интеграции с таймлайнами или временными шкалами значение времени становится управляющим параметром всей сцены.
function updateByTime(hour) {
map.setPaintProperty('night-layer', 'fill-opacity',
hour >= 20 || hour <= 6 ? 0.8 : 0
);
}
Подобные конструкции позволяют моделировать суточные циклы, сезонные изменения и другие временные процессы.
Изменение полного стиля карты также может быть анимировано, хотя это более тяжёлая операция.
map.setStyle('mapbox://styles/mapbox/dark-v11');
map.once('styledata', () => {
map.setPaintProperty('water', 'fill-color', '#001f3f');
});
Переключение стиля фактически пересоздаёт слои, поэтому временная логика часто переносится в события загрузки стиля.
На практике изменение свойств во времени редко ограничивается одним методом. Обычно используется комбинация:
requestAnimationFrame для точного контроляsetData для обновления геометрииsetPaintProperty для визуальных параметровeaseTo для камерыТак формируется единая временная сцена, где каждый слой реагирует на общий временной параметр.
Частые изменения свойств требуют учёта нагрузки на рендеринг:
setPaintPropertysetDataОсобенно критичны обновления источников данных, так как они инициируют перерасчёт геометрии и перерисовку слоёв.
Распространённый подход — введение единой переменной времени, управляющей всей сценой:
let time = 0;
function tick() {
time += 0.016;
map.setPaintProperty('layer-1', 'opacity', Math.sin(time));
map.setPaintProperty('layer-2', 'circle-radius', 5 + Math.cos(time) * 3);
requestAnimationFrame(tick);
}
tick();
Такое решение позволяет синхронизировать визуальные эффекты, создавая единый временной контекст карты.