Методы setData и getSource

В архитектуре Mapbox GL JS источники (sources) являются фундаментальным слоем данных, на котором строится визуализация карты. Каждый слой (layer) опирается на источник, а обновление данных в реальном времени часто происходит через методы, связанные с источниками.

Два ключевых метода для динамической работы с данными — setData и getSource — используются для управления GeoJSON-источниками и получения доступа к их состоянию.


GeoJSON-источник как основа динамических данных

Наиболее гибкий тип источника в Mapbox GL JS — geojson. Он позволяет обновлять данные без перезагрузки карты, что критично для:

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

Пример базового источника:

map.addSource('points', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: []
  }
});

Метод setData

Назначение

setData используется для полной замены данных внутри GeoJSON-источника. Он не изменяет существующий объект частично, а перезаписывает весь набор данных.

Сигнатура

source.setData(data);

Параметры

  • data — объект GeoJSON (Feature, FeatureCollection или URL к GeoJSON)

Особенности работы setData

Полная перезапись состояния

Каждый вызов setData заменяет текущие данные источника:

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

Поддерживаемые форматы

// FeatureCollection
{
  type: 'FeatureCollection',
  features: [...]
}

// Feature
{
  type: 'Feature',
  geometry: {...},
  properties: {...}
}

// URL
'https://example.com/data.geojson'

Пример использования setData

Обновление точек на карте

const source = map.getSource('points');

source.setData({
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [71.4304, 51.1284]
      },
      properties: {
        title: 'Объект A'
      }
    }
  ]
});

Частота вызова и производительность

setData является ресурсоёмкой операцией, так как:

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

Рекомендуется:

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

Паттерны оптимизации

Батчевое обновление

function updatePoints(points) {
  const features = points.map(p => ({
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: p.coords
    },
    properties: p.props
  }));

  map.getSource('points').setData({
    type: 'FeatureCollection',
    features
  });
}

Кэширование данных

При частичных изменениях часто эффективнее:

  • хранить локальное состояние
  • пересобирать FeatureCollection только при изменении

Метод getSource

Назначение

getSource используется для получения объекта источника по его идентификатору. Это основной способ доступа к источнику после его регистрации через addSource.


Сигнатура

map.getSource(id);

Параметры

  • id — строковый идентификатор источника

Возвращаемое значение

Метод возвращает объект источника, соответствующий типу:

  • GeoJSONSource
  • VectorSource
  • RasterSource
  • ImageSource
  • VideoSource

Для динамического изменения данных применяется только GeoJSONSource.


Пример использования getSource

const source = map.getSource('points');

Дальнейшая работа зависит от типа источника:

if (source && source.setData) {
  source.setData(newData);
}

Проверка существования источника

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

if (map.getSource('points')) {
  map.getSource('points').setData(data);
}

Типизация и ограничения

GeoJSONSource

Поддерживает:

  • setData
  • loaded
  • serialize

Не поддерживает:

  • частичное обновление features
  • мутацию внутренних объектов без setData

Типичные ошибки при работе с getSource

Обращение до загрузки карты

map.getSource('points').setData(data); // ошибка, если карта не готова

Решение — использовать событие:

map.on('load', () => {
  map.getSource('points').setData(data);
});

Неправильный тип источника

const source = map.getSource('vector-data');
source.setData(data); // ошибка, если источник не GeoJSON

Совместная работа setData и getSource

Оба метода часто используются вместе для управления состоянием данных:

map.on('load', () => {
  const source = map.getSource('points');

  source.setData({
    type: 'FeatureCollection',
    features: []
  });
});

В более сложных сценариях структура выглядит так:

  1. Получение источника через getSource
  2. Формирование новой GeoJSON-структуры
  3. Передача в setData
  4. Автоматическое обновление слоёв

Обновление данных в реальном времени

При потоковой передаче данных (например, GPS-трекинг) используется циклическое обновление:

setInterval(() => {
  const source = map.getSource('track');

  source.setData({
    type: 'FeatureCollection',
    features: getLatestTrack()
  });
}, 1000);

Геометрическая консистентность данных

При использовании setData важно соблюдать корректность GeoJSON:

  • обязательное поле type
  • валидная структура координат
  • согласованность geometry type и coordinates

Некорректные данные приводят к:

  • игнорированию features
  • частичной отрисовке
  • ошибкам в консоли браузера

Обновление без потери состояния

Так как setData полностью заменяет источник, для сохранения состояния применяется паттерн merge:

const source = map.getSource('points');

const current = source._data;

source.setData({
  type: 'FeatureCollection',
  features: [
    ...current.features,
    newFeature
  ]
});

Взаимодействие с слоями

Любой слой, связанный с GeoJSON-источником:

map.addLayer({
  id: 'points-layer',
  type: 'circle',
  source: 'points'
});

автоматически реагирует на:

  • setData
  • изменение FeatureCollection
  • обновление геометрии

без необходимости ручного перерисовывания.


Поведение при больших объёмах данных

При работе с тысячами объектов:

  • setData становится узким местом
  • увеличивается время перерисовки
  • возрастает нагрузка на main thread

Рекомендуемые подходы:

  • кластеризация
  • упрощение геометрии
  • фильтрация данных до передачи в setData

Итоговая модель взаимодействия

  • getSource — точка доступа к объекту источника
  • setData — механизм полной замены данных GeoJSON
  • их совместное использование формирует основу динамических карт в Mapbox GL JS