В MapLibre GL JS динамическое обновление данных строится вокруг
управления источниками (sources), подключёнными к стилю
карты. Наиболее гибкий и часто используемый вариант — источник типа
geojson, который поддерживает прямую замену данных в
рантайме без пересоздания слоя или переинициализации карты.
Для GeoJSON-источника предусмотрен метод setData,
доступный через объект источника, полученный из карты:
const source = map.getSource('points-source');
source.setData({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.31413, 59.93863]
},
properties: {
id: 1,
value: 42
}
}
]
});
При вызове setData происходит полная замена внутреннего
набора данных источника. Это означает:
Обновление является атомарной операцией: промежуточные состояния не отображаются на карте.
Источник типа geojson ожидает строго валидный
GeoJSON:
FeatureCollection;[долгота, широта];properties) могут содержать любые
сериализуемые данные.Некорректная структура приводит к игнорированию обновления без критической ошибки в большинстве случаев, поэтому контроль данных выполняется на уровне приложения.
Обновление данных происходит асинхронно относительно рендер-цикла карты.
После вызова setData выполняется цепочка этапов:
Если источник используется в нескольких слоях (fill, circle, line), все они получают обновлённые данные одновременно.
При работе с тысячами или миллионами объектов вызов
setData становится потенциально тяжёлой операцией.
Ключевые особенности:
Для потоковых данных применяется стратегия батчинга:
let buffer = [];
function pushUpdate(feature) {
buffer.push(feature);
if (buffer.length > 500) {
flush();
}
}
function flush() {
const source = map.getSource('stream');
source.setData({
type: 'FeatureCollection',
features: buffer
});
buffer = [];
}
Такой подход снижает количество пересборок геопространственного индекса.
MapLibre GL JS не поддерживает частичное обновление отдельных фич внутри GeoJSON-источника. Любое изменение требует пересборки всего объекта.
Поэтому используется паттерн иммутабельности:
features;setData с новым объектом.const source = map.getSource('objects');
const updated = currentFeatures.map(f =>
f.properties.id === 10
? {
...f,
properties: {
...f.properties,
value: 99
}
}
: f
);
source.setData({
type: 'FeatureCollection',
features: updated
});
Такой подход сохраняет предсказуемость состояния данных.
При включённой кластеризации (cluster: true) каждое
обновление данных инициирует перерасчёт кластеров.
Пример конфигурации:
map.addSource('clusters', {
type: 'geojson',
data: geojsonData,
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
После вызова setData:
cluster-фичи;Частые обновления в таком режиме требуют дополнительной оптимизации
(например, снижение частоты вызова setData или
предварительная агрегация данных).
Для raster и vector источников прямой
замены данных через setData не предусмотрено. Эти источники
опираются на тайлы, поэтому обновление происходит через:
tiles параметров через setStyle
или пересоздание источника.map.removeSource('raster-source');
map.addSource('raster-source', {
type: 'raster',
tiles: ['https://example.com/tiles/{z}/{x}/{y}.png']
});
Для image источников обновление выполняется через
изменение URL или координат:
const source = map.getSource('overlay');
source.updateImage({
url: 'https://example.com/new.png',
coordinates: [
[30, 60],
[31, 60],
[31, 59],
[30, 59]
]
});
MapLibre GL JS предоставляет набор событий для отслеживания состояния загрузки и обновления источников:
sourcedata — изменения в данных источника;data — общие изменения данных карты;dataloading — начало загрузки;idle — завершение всех активных операций.Пример отслеживания обновлений:
map.on('sourcedata', (e) => {
if (e.sourceId === 'points-source') {
// обработка обновления источника
}
});
Эти события используются для синхронизации UI и внешних систем с состоянием карты.
Перед вызовом setData важно убедиться, что источник уже
добавлен в стиль карты.
Типовой подход:
if (map.isSourceLoaded('points-source')) {
map.getSource('points-source').setData(newData);
}
Если источник ещё не загружен, обновление может быть проигнорировано или вызвать ошибку доступа к объекту.
Альтернативный подход — ожидание события load:
map.on('load', () => {
const source = map.getSource('points-source');
source.setData(initialData);
});
При работе с WebSocket или другими потоковыми источниками данных применяется модель непрерывного обновления:
const update = throttle((data) => {
map.getSource('stream').setData({
type: 'FeatureCollection',
features: data
});
}, 200);
Такая схема предотвращает перегрузку рендер-цикла и снижает количество перерасчётов геометрии.
При проектировании систем с частыми обновлениями источников учитываются следующие факторы:
setData.Оптимизационные стратегии:
При высокочастотных обновлениях возможны эффекты:
MapLibre GL JS оптимизирует рендеринг, поэтому промежуточные вызовы
setData могут быть объединены в один кадр отрисовки, что
снижает нагрузку, но повышает важность правильного батчинга на уровне
приложения.