Временные данные (temporal data) представляют собой информацию, изменяющуюся во времени. В геоинформационных системах такие данные используются для отображения движения объектов, изменения состояний территорий, динамики погодных явлений, транспортных потоков, маршрутов доставки, экологических показателей и множества других процессов.
Mapbox GL JS предоставляет инструменты для визуализации и анимации временных данных на интерактивных картах с использованием JavaScript, GeoJSON, выражений (Expressions), пользовательских источников данных и механизмов обновления слоёв в реальном времени.
Каждый объект временного набора данных содержит не только пространственные координаты, но и временную составляющую.
Пример GeoJSON с временной меткой:
{
"type": "Feature",
"properties": {
"timestamp": "2025-05-15T10:30:00Z",
"speed": 60
},
"geometry": {
"type": "Point",
"coordinates": [37.6176, 55.7558]
}
}
Основные типы временных данных:
| Тип | Описание |
|---|---|
| Мгновенные события | Происходят в конкретный момент времени |
| Интервалы | Имеют начало и конец |
| Траектории | Последовательность точек движения |
| Потоки данных | Непрерывное поступление информации |
| Исторические данные | Архив событий за длительный период |
Mapbox GL JS не имеет специального поля для времени. Временные
значения обычно размещаются в объекте properties.
Пример:
{
"type": "Feature",
"properties": {
"time": 1715745600000,
"temperature": 24
},
"geometry": {
"type": "Point",
"coordinates": [30.3158, 59.9391]
}
}
Время может храниться в различных форматах:
"2025-05-15T12:00:00Z"
1715745600
1715745600000
"15.05.2025 12:00"
Для дальнейшей фильтрации и анимации наиболее удобен формат Unix Timestamp.
Часто требуется отобразить набор измерений, собранных в разные моменты времени.
Пример массива данных:
const points = [
{
time: 1715745600,
coordinates: [37.6176, 55.7558]
},
{
time: 1715745660,
coordinates: [37.6181, 55.7562]
},
{
time: 1715745720,
coordinates: [37.6190, 55.7570]
}
];
Преобразование в GeoJSON:
const geojson = {
type: 'FeatureCollection',
features: points.map(item => ({
type: 'Feature',
properties: {
time: item.time
},
geometry: {
type: 'Point',
coordinates: item.coordinates
}
}))
};
Добавление источника:
map.addSource('history', {
type: 'geojson',
data: geojson
});
Один из самых распространённых сценариев — отображение только тех объектов, которые относятся к определённому временному диапазону.
Добавление слоя:
map.addLayer({
id: 'events',
type: 'circle',
source: 'history',
paint: {
'circle-radius': 6,
'circle-color': '#007cbf'
}
});
Фильтрация:
const currentTime = 1715745660;
map.setFilter('events', [
'<=',
['get', 'time'],
currentTime
]);
На карте будут отображаться только объекты, время которых меньше либо равно указанному значению.
Для интерактивного управления временем обычно используется HTML-слайдер.
HTML:
<input
id="timeline"
type="range"
min="0"
max="100"
value="0"
/>
Jav * aScript:
const slider = document.getElementById('timeline');
slider.addEventListener('input', e => {
const value = Number(e.target.value);
map.setFilter('events', [
'<=',
['get', 'time'],
value
]);
});
При перемещении ползунка карта мгновенно обновляется.
Вместо ручного управления временная шкала может изменяться автоматически.
Пример:
let currentTime = 0;
function animate() {
map.setFilter('events', [
'<=',
['get', 'time'],
currentTime
]);
currentTime += 1;
requestAnimationFrame(animate);
}
animate();
Функция requestAnimationFrame() обеспечивает плавную
анимацию и синхронизируется с частотой обновления браузера.
Одной из наиболее популярных задач является отображение движения транспорта.
Подготовка маршрута:
const route = [
[37.6176, 55.7558],
[37.6182, 55.7565],
[37.6191, 55.7574],
[37.6200, 55.7581]
];
Источник:
map.addSource('vehicle', {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: route[0]
}
}
});
Слой:
map.addLayer({
id: 'vehicle',
type: 'circle',
source: 'vehicle',
paint: {
'circle-radius': 8,
'circle-color': '#ff0000'
}
});
Анимация:
let index = 0;
function moveVehicle() {
const source = map.getSource('vehicle');
source.setData({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: route[index]
}
});
index = (index + 1) % route.length;
setTimeout(moveVehicle, 500);
}
moveVehicle();
Часто одновременно показываются текущее положение объекта и пройденный путь.
Источник:
map.addSource('track', {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: []
}
}
});
Обновление маршрута:
const passedPoints = [];
function updateTrack(point) {
passedPoints.push(point);
map.getSource('track').setData({
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: passedPoints
}
});
}
Линия будет постепенно увеличиваться по мере движения объекта.
При редких измерениях движение может выглядеть скачкообразным.
Линейная интерполяция позволяет вычислять промежуточные координаты.
Функция:
function interpolate(start, end, factor) {
return [
start[0] + (end[0] - start[0]) * factor,
start[1] + (end[1] - start[1]) * factor
];
}
Использование:
const position = interpolate(
route[0],
route[1],
0.5
);
Результатом станет точка посередине между двумя координатами.
При большом количестве объектов частое обновление GeoJSON может вызывать снижение производительности.
В таких случаях полезно использовать механизм состояний объектов.
Установка состояния:
map.setFeatureState(
{
source: 'vehicles',
id: 10
},
{
active: true
}
);
Получение состояния в стиле:
'circle-color': [
'case',
['feature-state', 'active'],
'#ff0000',
'#00ff00'
]
Изменение состояния происходит значительно быстрее, чем полное обновление источника.
Многие приложения получают информацию через WebSocket.
Подключение:
const socket = new WebSocket(
'wss://example.com/tracking'
);
Получение данных:
socket.onmess age = event => {
const position = JSON.parse(event.data);
map.getSource('vehicle').setData({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
position.lng,
position.lat
]
}
});
};
Карта обновляется сразу после поступления новых данных.
Тепловая карта может отображать плотность событий за конкретный временной период.
Источник:
map.addSource('events', {
type: 'geojson',
data: eventsData
});
Слой:
map.addLayer({
id: 'heatmap',
type: 'heatmap',
source: 'events'
});
Фильтрация по времени:
map.setFilter('heatmap', [
'all',
['>=', ['get', 'time'], startTime],
['<=', ['get', 'time'], endTime]
]);
В результате отображаются только события выбранного интервала.
Некоторые объекты существуют в течение определённого периода.
Пример:
{
"start": 1715745600,
"end": 1715752800
}
Фильтрация:
map.setFilter('objects', [
'all',
['<=', ['get', 'start'], currentTime],
['>=', ['get', 'end'], currentTime]
]);
Объект будет отображаться только тогда, когда текущее время находится внутри заданного интервала.
Скорость анимации может изменяться динамически.
Пример:
let playbackSpeed = 1;
Изменение:
playbackSpeed = 4;
Обновление времени:
currentTime += playbackSpeed;
Подобный механизм позволяет реализовать ускоренное воспроизведение исторических данных.
При работе с большими архивами целесообразно сохранять уже загруженные данные.
Пример:
const cache = new Map();
Сохранение:
cache.set(timeRange, geojson);
Получение:
const data = cache.get(timeRange);
Кэширование существенно уменьшает количество сетевых запросов.
При работе с временными данными объём информации быстро возрастает. Для поддержания высокой производительности используются следующие подходы:
Ограничение количества отображаемых объектов
features.slice(-1000);
Упрощение геометрии
LineString → меньшее количество вершин
Использование векторных тайлов
type: 'vector'
Обновление только изменившихся объектов
setFeatureState()
Пакетная обработка данных
requestAnimationFrame()
Кластеризация временных точек
cluster: true
Полноценная система работы с временными данными в Mapbox GL JS обычно состоит из нескольких уровней:
Схема потока данных:
Сервер
↓
Получение данных
↓
GeoJSON
↓
Map Source
↓
Filter
↓
Layer
↓
Отображение на карте
Такая архитектура позволяет эффективно визуализировать как исторические архивы, так и непрерывно поступающие данные в реальном времени, сохраняя высокую производительность интерфейса и плавность отображения пространственно-временных процессов.