Визуализация данных в Mapbox GL JS строится вокруг концепции источников (sources). Источник определяет, откуда карта получает данные и в каком формате они поступают в рендеринг. Каждый источник описывается один раз и затем может использоваться в одном или нескольких слоях (layers). Архитектура разделяет данные и их отображение, что позволяет гибко управлять визуализацией без дублирования информации.
Mapbox предоставляет инфраструктуру для хранения и доставки геоданных, включая векторные тайлы и tilesets, однако Mapbox GL JS поддерживает и полностью независимые источники, такие как GeoJSON и внешние API.
addSourceОсновной метод подключения данных — map.addSource. Он
регистрирует источник в экземпляре карты и делает его доступным для
слоёв.
map.on('load', () => {
map.addSource('cities', {
type: 'geojson',
data: 'https://example.com/cities.geojson'
});
});
Важный момент: добавление источников выполняется только после события
load, когда стиль и базовая инфраструктура карты уже
инициализированы.
Источники бывают разных типов, и от типа зависит структура конфигурации.
GeoJSON — наиболее универсальный формат для загрузки пользовательских данных. Он подходит для точек, линий и полигонов.
map.addSource('earthquakes', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [37.62, 55.75]
},
properties: {
magnitude: 4.2
}
}
]
}
});
GeoJSON может быть как встроенным объектом, так и URL-адресом. Во втором случае данные загружаются асинхронно и автоматически обновляются при изменении ресурса.
setDataДля источников типа GeoJSON предусмотрено динамическое обновление без пересоздания источника.
const source = map.getSource('earthquakes');
source.setData({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.31, 59.93]
},
properties: {
magnitude: 3.8
}
}
]
});
Механизм setData пересчитывает только затронутые части
рендера, что делает его подходящим для частых обновлений, например в
реальном времени.
Векторные тайлы представляют собой оптимизированный способ доставки больших объёмов геоданных. Они разделяют данные на фрагменты (tiles), которые загружаются по мере необходимости.
map.addSource('buildings', {
type: 'vector',
url: 'mapbox://examples.8fgz4egr'
});
Каждый слой внутри векторного источника обращается к конкретному слою
тайлсета через параметр source-layer.
map.addLayer({
id: 'building-fill',
type: 'fill-extrusion',
source: 'buildings',
'source-layer': 'building',
paint: {
'fill-extrusion-color': '#aaa',
'fill-extrusion-height': 50
}
});
Векторные тайлы особенно эффективны при работе с большими наборами данных, такими как здания, дороги, административные границы.
Растровые данные представляют собой изображения, разделённые на тайлы. Они используются для спутниковых снимков, тепловых карт или любых предрендеренных визуализаций.
map.addSource('satellite', {
type: 'raster',
tiles: [
'https://example.com/tiles/{z}/{x}/{y}.png'
],
tileSize: 256
});
Растровые источники не содержат семантики объектов — они отображают готовую графику.
Источник типа image позволяет наложить одно изображение
на карту с привязкой к координатам.
map.addSource('overlay', {
type: 'image',
url: 'https://example.com/image.png',
coordinates: [
[-80, 35],
[-70, 35],
[-70, 45],
[-80, 45]
]
});
Этот тип часто применяется для исторических карт, схем или пользовательских наложений.
Mapbox GL JS поддерживает видео как источник данных, где каждый кадр интерпретируется как текстура.
map.addSource('drone', {
type: 'video',
urls: [
'https://example.com/video.mp4'
],
coordinates: [
[-122.5155, 37.5634],
[-122.5140, 37.5634],
[-122.5140, 37.5647],
[-122.5155, 37.5647]
]
});
Видео-источники применяются в аналитике и визуализации потоковых данных.
Для больших наборов точек используется кластеризация, которая объединяет близкие объекты в агрегированные группы.
map.addSource('incidents', {
type: 'geojson',
data: '/incidents.geojson',
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
Кластеры доступны как отдельные точки с дополнительными свойствами:
point_count — количество объединённых точекcluster — флаг принадлежности к кластеруОтдельные слои могут визуализировать кластеры и отдельные точки одновременно.
Данные не всегда нужно менять на уровне источника. Часто используется фильтрация на уровне слоя.
map.addLayer({
id: 'large-earthquakes',
type: 'circle',
source: 'earthquakes',
filter: ['>=', ['get', 'magnitude'], 5],
paint: {
'circle-radius': 8,
'circle-color': 'red'
}
});
Фильтры работают на GPU-уровне и позволяют избегать лишних вычислений в JavaScript.
Источники можно заменять полностью, что полезно при переключении наборов данных.
map.removeSource('cities');
map.addSource('cities', {
type: 'geojson',
data: '/new-cities.geojson'
});
Такой подход используется при переключении тематических слоёв или регионов.
При работе с защищёнными API или нестандартными заголовками
применяется transformRequest.
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
transformRequest: (url, resourceType) => {
return {
url: url,
headers: {
'Authorization': 'Bearer TOKEN'
}
};
}
});
Это позволяет контролировать все сетевые запросы, включая загрузку тайлов и GeoJSON.
Mapbox GL JS использует внутренний кэш тайлов, что снижает нагрузку на сеть и ускоряет повторное отображение данных. Векторные и растровые тайлы загружаются лениво — только при попадании в область видимости.
При панорамировании и масштабировании карта переиспользует ранее загруженные данные, минимизируя количество запросов.
Система рендеринга распределяет приоритеты загрузки:
Это обеспечивает стабильную интерактивность даже при сложных слоях.
Источники могут ссылаться на динамические API, возвращающие GeoJSON.
map.addSource('traffic', {
type: 'geojson',
data: 'https://api.example.com/traffic?bbox={bbox}'
});
Подобные схемы часто комбинируются с серверной генерацией данных в зависимости от области карты.
При работе с миллионами объектов основное значение имеет выбор типа источника:
Оптимизация достигается не только за счёт формата, но и через ограничение количества отображаемых слоёв и использование фильтров на уровне GPU.