Создание источника из URL

Mapbox GL JS поддерживает работу с удалёнными источниками данных напрямую по URL, что является ключевым механизмом построения масштабируемых картографических приложений. Источник (source) в архитектуре Mapbox GL JS представляет собой абстракцию над геоданными, которые могут поступать в различных форматах: GeoJSON, векторные тайлы, растровые тайлы или изображения. Подключение источника через URL позволяет отделить данные от клиентской логики и делегировать их хранение и обновление серверной инфраструктуре.

Наиболее распространённый сценарий — подключение GeoJSON-файла по прямой ссылке. В этом случае Mapbox GL JS выполняет HTTP-запрос и интерпретирует полученный JSON как географические данные.

map.on('load', () => {
  map.addSource('cities', {
    type: 'geojson',
    data: 'https://example.com/data/cities.geojson'
  });

  map.addLayer({
    id: 'cities-points',
    type: 'circle',
    source: 'cities',
    paint: {
      'circle-radius': 6,
      'circle-color': '#1da1f2'
    }
  });
});

При использовании URL важно учитывать, что библиотека кэширует результат загрузки до перезагрузки источника. Обновление данных требует явного вызова setData, если источник уже загружен и переключается на локальные данные.

Динамическая загрузка GeoJSON через fetch

В ряде случаев требуется предварительная обработка данных перед передачей в Mapbox GL JS. Тогда используется стандартный fetch, после чего результат передаётся как объект.

map.on('load', async () => {
  const response = await fetch('https://example.com/data/earthquakes.geojson');
  const geojson = await response.json();

  map.addSource('earthquakes', {
    type: 'geojson',
    data: geojson
  });

  map.addLayer({
    id: 'earthquakes-layer',
    type: 'circle',
    source: 'earthquakes',
    paint: {
      'circle-radius': 4,
      'circle-color': '#e63946'
    }
  });
});

Такой подход позволяет выполнять фильтрацию, агрегацию или преобразование структуры данных до их попадания в рендеринговый конвейер.

Векторные тайлы из URL

Векторные источники представляют собой более производительный вариант для больших наборов данных. Они загружаются по шаблону URL, где координаты тайла подставляются динамически.

map.addSource('countries', {
  type: 'vector',
  tiles: [
    'https://example.com/tiles/countries/{z}/{x}/{y}.pbf'
  ],
  minzoom: 0,
  maxzoom: 6
});

Использование {z}/{x}/{y} позволяет Mapbox GL JS запрашивать только те тайлы, которые необходимы для текущего viewport. Это фундаментальный механизм оптимизации производительности при работе с глобальными наборами данных.

При добавлении слоя необходимо указать source-layer, так как один векторный тайл может содержать несколько логических слоёв данных.

map.addLayer({
  id: 'countries-fill',
  type: 'fill',
  source: 'countries',
  'source-layer': 'country_boundaries',
  paint: {
    'fill-color': '#a8dadc',
    'fill-opacity': 0.6
  }
});

Растровые источники по URL

Растровые источники применяются для подложек, спутниковых снимков и тайлов изображений.

map.addSource('satellite', {
  type: 'raster',
  tiles: [
    'https://example.com/tiles/satellite/{z}/{x}/{y}.png'
  ],
  tileSize: 256
});

Растровые данные не требуют интерпретации структуры, что делает их проще, но менее гибкими по сравнению с векторными источниками.

Источники с контролем запросов через transformRequest

При работе с защищёнными API или CDN часто требуется добавление токенов авторизации или модификация заголовков запроса. Mapbox GL JS предоставляет механизм transformRequest, который перехватывает каждый сетевой запрос.

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v11',
  transformRequest: (url, resourceType) => {
    if (resourceType === 'Tile' || resourceType === 'Source') {
      return {
        url: url,
        headers: {
          'Authorization': 'Bearer TOKEN'
        }
      };
    }
  }
});

Этот механизм особенно важен при работе с приватными тайловыми сервисами и корпоративными геоданными.

Обновление источника после загрузки

После добавления GeoJSON-источника его содержимое можно изменять без переинициализации слоя.

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

fetch('https://example.com/data/new-cities.geojson')
  .then(res => res.json())
  .then(data => {
    source.setData(data);
  });

Этот подход используется для реализации realtime-обновлений, например, отображения движения объектов или потоковых данных сенсоров.

Асинхронная природа загрузки источников

Источники, подключённые через URL, загружаются асинхронно. Это означает, что слой, использующий источник, должен создаваться после события load карты или после события sourcedata.

map.on('sourcedata', (e) => {
  if (e.sourceId === 'cities' && e.isSourceLoaded) {
    console.log('Источник загружен');
  }
});

Контроль состояния загрузки особенно важен при каскадном добавлении слоёв, зависящих от одного источника.

Кэширование и повторное использование данных

Mapbox GL JS использует внутреннее кэширование тайлов и GeoJSON-ответов. При повторном использовании URL без изменения параметров запрос не выполняется повторно, если ресурс считается актуальным.

Для принудительного обновления часто применяют добавление query-параметров:

map.getSource('cities').setData(
  'https://example.com/data/cities.geojson?version=2'
);

Такой приём используется в системах с частым обновлением данных, где требуется обход HTTP-кэша.

Ограничения и особенности загрузки из URL

При работе с удалёнными источниками необходимо учитывать ограничения CORS. Сервер, предоставляющий GeoJSON или тайлы, должен возвращать корректные заголовки доступа, иначе запросы будут заблокированы браузером.

Также важно учитывать размер GeoJSON-файлов: при превышении определённого объёма производительность резко падает, поскольку вся структура загружается и парсится на клиенте. В таких случаях предпочтение отдаётся векторным тайлам.

Комбинирование нескольких URL-источников

В одной карте могут сосуществовать разные типы URL-источников: GeoJSON для динамических объектов, векторные тайлы для базовой географии и растровые слои для подложки.

map.on('load', () => {
  map.addSource('base', {
    type: 'raster',
    tiles: ['https://example.com/tiles/base/{z}/{x}/{y}.png']
  });

  map.addSource('features', {
    type: 'geojson',
    data: 'https://example.com/data/features.geojson'
  });

  map.addSource('admin', {
    type: 'vector',
    tiles: ['https://example.com/tiles/admin/{z}/{x}/{y}.pbf']
  });
});

Такая композиция формирует многоуровневую архитектуру отображения, где каждый источник выполняет строго определённую роль в визуализации данных.