Mapbox GL JS представляет собой высокоуровневый слой управления WebGL-рендерингом карт, где пользовательские сценарии строятся вокруг связки источников данных (sources), визуальных слоёв (layers), камеры (camera), состояния приложения и событий взаимодействия. Полные сценарии в таких системах не ограничиваются отображением карты — они включают поток данных, управление состоянием, визуальную агрегацию и реакцию интерфейса на изменения геопространственной информации.
В основе любых сложных сценариев лежит модель:
Типичный сценарий формируется как реактивная система:
setData() или обновление tile
sourcemap.addSource('orders', {
type: 'geojson',
data: '/api/orders'
});
map.addLayer({
id: 'orders-layer',
type: 'circle',
source: 'orders',
paint: {
'circle-radius': 6,
'circle-color': '#3b82f6'
}
});
Сценарий доставки строится вокруг постоянного обновления координат объектов (курьеров, заказов, транспорта). Основной механизм — обновление GeoJSON источника.
Ключевые элементы:
setDataconst source = map.getSource('couriers');
socket.on('courier:update', (data) => {
const geojson = {
type: 'FeatureCollection',
features: data.map(courier => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: courier.coords
},
properties: {
status: courier.status
}
}))
};
source.setData(geojson);
});
Для плавности движения применяется интерполяция координат:
requestAnimationFrameСлой может изменять стиль в зависимости от состояния:
map.setPaintProperty('couriers-layer', 'circle-color', [
'match',
['get', 'status'],
'active', '#22c55e',
'delayed', '#f59e0b',
'#ef4444'
]);
Геоданные объектов недвижимости обычно имеют высокую плотность, что требует кластеризации.
Основные компоненты:
cluster: truemap.addSource('real-estate', {
type: 'geojson',
data: '/api/houses',
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
Отображение кластеров:
map.addLayer({
id: 'clusters',
type: 'circle',
source: 'real-estate',
filter: ['has', 'point_count'],
paint: {
'circle-radius': [
'step',
['get', 'point_count'],
15, 10,
25, 50,
35
],
'circle-color': '#6366f1'
}
});
Логика пользовательского сценария:
Фильтрация реализуется через setFilter:
map.setFilter('unclustered-point', [
'all',
['>=', ['get', 'price'], 100000],
['<=', ['get', 'price'], 300000]
]);
Аналитические сценарии включают heatmap и choropleth.
Heatmap используется для плотности событий:
map.addLayer({
id: 'heatmap',
type: 'heatmap',
source: 'events',
paint: {
'heatmap-intensity': 1,
'heatmap-radius': 20,
'heatmap-color': [
'interpolate',
['linear'],
['heatmap-density'],
0, 'rgba(0,0,255,0)',
1, 'rgba(255,0,0,1)'
]
}
});
Choropleth-карты строятся на основе полигонов:
map.addLayer({
id: 'regions-fill',
type: 'fill',
source: 'regions',
paint: {
'fill-color': [
'interpolate',
['linear'],
['get', 'value'],
0, '#f3f4f6',
100, '#60a5fa',
500, '#1e3a8a'
]
}
});
Маршрутизация обычно строится через внешний API, но визуализация полностью ложится на GL JS.
Компоненты:
map.addSource('route', {
type: 'geojson',
data: routeGeoJSON
});
map.addLayer({
id: 'route-line',
type: 'line',
source: 'route',
paint: {
'line-width': 4,
'line-color': '#10b981'
}
});
Анимация движения вдоль маршрута:
map.flyTo({
center: route.coordinates[0],
zoom: 14,
speed: 1.2
});
3D-сценарии используют extrusion и terrain.
Extrusion зданий:
map.addLayer({
id: 'buildings',
type: 'fill-extrusion',
source: 'composite',
'source-layer': 'building',
paint: {
'fill-extrusion-height': ['get', 'height'],
'fill-extrusion-color': '#94a3b8',
'fill-extrusion-opacity': 0.8
}
});
Terrain добавляет рельеф:
map.setTerrain({
source: 'mapbox-dem',
exaggeration: 1.5
});
Камера становится частью сценария:
Геозоны реализуются на стороне клиента:
function isInsideZone(point, polygon) {
return turf.booleanPointInPolygon(point, polygon);
}
При обновлении координат:
Применяется для:
Высоконагруженные сценарии требуют:
Подход обновления:
setData чаще 10–15 раз/секlet queue = [];
function pushUpdate(point) {
queue.push(point);
}
setInterval(() => {
if (!queue.length) return;
const data = buildGeoJSON(queue);
map.getSource('live').setData(data);
queue = [];
}, 100);
Карты в сложных приложениях должны быть частью общего состояния приложения.
Синхронизация включает:
map.on('moveend', () => {
const center = map.getCenter();
const zoom = map.getZoom();
history.replaceState(null, '', `#z=${zoom}&lat=${center.lat}&lng=${center.lng}`);
});
При восстановлении состояния:
Типичные режимы:
Переключение режимов означает:
function setMode(mode) {
map.setLayoutProperty('heatmap', 'visibility', mode === 'analytics' ? 'visible' : 'none');
map.setLayoutProperty('route-line', 'visibility', mode === 'navigation' ? 'visible' : 'none');
}
Кастомные источники применяются для:
Стратегия:
function normalize(sensorData) {
return {
type: 'FeatureCollection',
features: sensorData.map(d => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [d.lon, d.lat]
},
properties: d
}))
};
}
В SPA архитектуре карта:
Типовой цикл:
map.removeLayer('layer-id');
map.removeSource('source-id');
Сценарии полного цикла формируются вокруг постоянного взаимодействия: