GeoJSON представляет собой стандарт обмена геопространственными данными, основанный на JSON-структуре. В контексте визуализации карт он используется как основной формат для описания точек, линий и полигонов, а также их атрибутов. В Mapbox GL JS GeoJSON является ключевым источником данных для слоёв, фильтрации, стилизации и интерактивности.
Структура GeoJSON строится вокруг объекта FeatureCollection, содержащего массив Feature-объектов. Каждый Feature включает геометрию (geometry) и свойства (properties), которые используются для стилизации и логики отображения.
Пример базовой структуры:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [69.5901, 42.3417]
},
"properties": {
"title": "Точка интереса",
"category": "poi"
}
}
]
}
GeoJSON может поступать в карту несколькими способами:
Наиболее простой вариант — передача объекта напрямую в источник данных:
map.on('load', () => {
map.addSource('points', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: []
}
});
});
Этот подход используется для небольших наборов данных, которые не требуют частого обновления.
GeoJSON может загружаться по URL:
map.addSource('cities', {
type: 'geojson',
data: 'https://example.com/cities.geojson'
});
Такой подход применяется для динамических или предварительно подготовленных наборов данных.
GeoJSON-источник может обновляться на лету:
map.getSource('cities').setData(updatedGeojson);
Это критически важно для приложений, где данные изменяются в реальном времени: трекинг объектов, аналитика, мониторинг.
После добавления источника создаются слои (layers), которые визуализируют данные.
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points',
paint: {
'circle-radius': 6,
'circle-color': '#ff5722'
}
});
Каждая точка GeoJSON отображается как круг с заданными стилями.
map.addLayer({
id: 'routes',
type: 'line',
source: 'routes',
paint: {
'line-color': '#3b82f6',
'line-width': 3
}
});
Используется для маршрутов, дорог, траекторий.
map.addLayer({
id: 'areas',
type: 'fill',
source: 'areas',
paint: {
'fill-color': '#22c55e',
'fill-opacity': 0.4
}
});
Применяется для отображения границ, зон покрытия, административных областей.
Одним из ключевых преимуществ GeoJSON является возможность связывать геометрию с данными.
В Mapbox GL JS свойства используются для data-driven styling:
map.addLayer({
id: 'points',
type: 'circle',
source: 'points',
paint: {
'circle-radius': [
'case',
['==', ['get', 'category'], 'large'], 10,
5
],
'circle-color': [
'match',
['get', 'category'],
'restaurant', '#e11d48',
'school', '#2563eb',
'#9ca3af'
]
}
});
Оператор get извлекает значения из properties, а
выражения case и match позволяют строить
условную визуализацию без дополнительного кода.
Mapbox GL JS поддерживает фильтрацию на уровне слоя:
map.setFilter('points', [
'==',
['get', 'category'],
'restaurant'
]);
Фильтрация выполняется на стороне рендерера и позволяет быстро переключать подмножества данных без изменения источника.
Для больших наборов точек GeoJSON используется кластеризация:
map.addSource('earthquakes', {
type: 'geojson',
data: '/earthquakes.geojson',
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
Кластеры автоматически группируют близкие точки, снижая нагрузку на рендеринг.
Отображение кластеров:
map.addLayer({
id: 'clusters',
type: 'circle',
source: 'earthquakes',
filter: ['has', 'point_count'],
paint: {
'circle-radius': 15,
'circle-color': '#f59e0b'
}
});
Отдельно можно отображать одиночные точки:
map.addLayer({
id: 'unclustered',
type: 'circle',
source: 'earthquakes',
filter: ['!', ['has', 'point_count']],
paint: {
'circle-radius': 6,
'circle-color': '#ef4444'
}
});
GeoJSON-слои интегрируются с системой событий карты:
map.on('click', 'points', (e) => {
const feature = e.features[0];
console.log(feature.properties.title);
});
Для корректной работы необходимо указать
queryRenderedFeatures через идентификатор слоя.
Также можно использовать hover-эффекты:
map.on('mouseenter', 'points', () => {
map.getCanvas().style.cursor = 'pointer';
});
GeoJSON-источники в Mapbox GL JS позволяют реализовать потоковые сценарии:
setInterval(() => {
fetch('/api/positions')
.then(res => res.json())
.then(data => {
map.getSource('vehicles').setData(data);
});
}, 5000);
Такая модель применяется для:
При больших объёмах данных важно учитывать производительность.
Сложные полигоны следует упрощать до загрузки:
Разделение GeoJSON на несколько источников снижает нагрузку на фильтрацию и рендеринг.
Слишком большие радиусы кластеров могут снижать точность визуализации.
GeoJSON часто формируется на серверной стороне или в ETL-процессах. Основные преобразования включают:
Пример формирования Feature:
const feature = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [longitude, latitude]
},
properties: {
id: 1,
status: 'active'
}
};
Один источник GeoJSON может использоваться несколькими слоями одновременно:
Пример heatmap:
map.addLayer({
id: 'heat',
type: 'heatmap',
source: 'points',
paint: {
'heatmap-intensity': 1,
'heatmap-radius': 20
}
});
Такая модель позволяет строить многослойные аналитические представления поверх одного набора данных.
В Mapbox GL JS выражения позволяют превращать GeoJSON в основу визуальной логики:
Пример масштабозависимого отображения:
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
5, 2,
10, 8,
15, 20
]
GeoJSON часто служит связующим звеном между картой и интерфейсом приложения:
Такая интеграция строится вокруг идентификаторов в properties и реактивного обновления источника данных.
При росте данных стандартный GeoJSON может стать узким местом. В таких случаях используются:
GeoJSON остаётся базовым форматом на уровне логики, но физическая доставка данных оптимизируется через более сложные структуры.