Mapbox GL JS представляет собой низкоуровневую библиотеку для рендеринга интерактивных карт на основе WebGL. Она тесно связана с экосистемой Mapbox и использует векторные тайлы, стили Mapbox Style Specification и GPU-ускоренный рендеринг для работы с большими наборами геоданных.
Интеграция начинается с подключения библиотеки и стилей:
<link href="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js"></script>
Контейнер под карту должен иметь фиксированную высоту, иначе WebGL-контекст не будет отображён:
<div id="map" style="width: 100%; height: 600px;"></div>
Ключевой элемент — access token. Он используется для авторизации запросов к API Mapbox:
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
Создание карты выполняется через конструктор Map:
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [69.2401, 53.2145],
zoom: 10
});
Параметры инициализации определяют базовое состояние:
container — DOM-элемент или его idstyle — URL стиля Mapboxcenter — начальные координаты [долгота, широта]zoom — уровень приближенияВажный момент архитектуры Mapbox GL JS — асинхронная загрузка стиля.
Все операции добавления слоёв должны выполняться после события
load:
map.on('load', () => {
// безопасное добавление источников и слоёв
});
Стили в Mapbox GL JS описываются через JSON-конфигурацию Mapbox Style Specification. Они включают источники данных, слои, фильтры и визуальные свойства.
Пример подключения готового стиля:
map.setStyle('mapbox://styles/mapbox/light-v11');
Система стилей основана на концепции слоёв:
Каждый слой связан с источником данных (source), что
делает архитектуру строго разделённой.
Mapbox использует векторные и растровые источники. Наиболее гибкий вариант — GeoJSON:
map.addSource('points', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [69.2401, 53.2145]
},
properties: {
title: 'Объект'
}
}
]
}
});
Источник сам по себе не отображается — он становится видимым только после добавления слоя:
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points',
paint: {
'circle-radius': 8,
'circle-color': '#ff5500'
}
});
Слои формируют визуальную структуру карты. Порядок слоёв критически важен, так как они отрисовываются сверху вниз.
Добавление слоя:
map.addLayer({
id: 'roads',
type: 'line',
source: 'composite',
'source-layer': 'road',
paint: {
'line-color': '#888',
'line-width': 2
}
});
Управление слоями включает:
setLayoutProperty — изменение структуры
отображенияsetPaintProperty — изменение визуального стиляmoveLayer — изменение порядкаПример динамического изменения прозрачности:
map.setPaintProperty('roads', 'line-opacity', 0.5);
Mapbox GL JS активно использует событийную модель. Основные события:
load — завершение загрузки стиляmove — изменение положения картыclick — взаимодействие с объектамиzoom — изменение масштабаПример обработки клика по карте:
map.on('click', (e) => {
console.log(e.lngLat);
});
Обработка клика по слоям:
map.on('click', 'points-layer', (e) => {
const feature = e.features[0];
console.log(feature.properties.title);
});
Геокодинг позволяет преобразовывать адреса в координаты и обратно. Обычно используется Mapbox Geocoding API.
Пример запроса:
fetch(`https://api.mapbox.com/geocoding/v5/mapbox.places/karaganda.json?access_token=${mapboxgl.accessToken}`)
.then(res => res.json())
.then(data => {
console.log(data.features);
});
Результаты можно напрямую использовать для центрирования карты:
map.flyTo({
center: data.features[0].center,
zoom: 12
});
Mapbox Directions API позволяет строить маршруты между точками.
Пример запроса маршрута:
fetch(`https://api.mapbox.com/directions/v5/mapbox/driving/69.2401,53.2145;69.1629,53.2833?geometries=geojson&access_token=${mapboxgl.accessToken}`)
.then(res => res.json())
.then(data => {
const route = data.routes[0].geometry;
});
Добавление маршрута на карту:
map.addSource('route', {
type: 'geojson',
data: {
type: 'Feature',
geometry: route
}
});
map.addLayer({
id: 'route-line',
type: 'line',
source: 'route',
paint: {
'line-color': '#1db7dd',
'line-width': 4
}
});
Маркер — базовый объект интерфейса:
const marker = new mapboxgl.Marker()
.setLngLat([69.2401, 53.2145])
.addTo(map);
Popup используется для отображения информации:
const popup = new mapboxgl.Popup()
.setLngLat([69.2401, 53.2145])
.setHTML('<h3>Объект</h3><p>Описание точки</p>')
.addTo(map);
Связка маркера и popup:
new mapboxgl.Marker()
.setLngLat([69.2401, 53.2145])
.setPopup(popup);
Mapbox GL JS поддерживает обновление источников без перерисовки всей карты:
const source = map.getSource('points');
source.setData({
type: 'FeatureCollection',
features: updatedFeatures
});
Этот механизм позволяет реализовать:
Фильтры применяются на уровне слоёв:
map.setFilter('points-layer', ['==', 'type', 'restaurant']);
Поддерживаются логические операторы:
==, !=>, <, >=,
<=in, all, anyПример сложного фильтра:
map.setFilter('points-layer', [
'all',
['==', 'type', 'restaurant'],
['>', 'rating', 4]
]);
Стили могут полностью заменять визуальную концепцию карты:
map.setStyle({
version: 8,
sources: {},
layers: []
});
Кастомные стили позволяют:
Mapbox GL JS использует WebGL, но требует соблюдения практик оптимизации:
Для больших наборов данных предпочтительны vector tiles:
map.addSource('tiles', {
type: 'vector',
url: 'mapbox://mapbox.mapbox-streets-v8'
});
Mapbox GL JS не изолирован от DOM-логики приложения. Он легко интегрируется с UI-фреймворками:
Пример синхронизации:
map.on('move', () => {
const center = map.getCenter();
updateUI(center);
});
Камера управляет перспективой и положением:
map.flyTo({
center: [69.2401, 53.2145],
zoom: 14,
speed: 1.2
});
Дополнительные методы:
easeTo — плавное перемещениеjumpTo — мгновенное изменениеfitBounds — подгонка под областьПример адаптации под границы:
map.fitBounds([
[68.9, 53.1],
[69.5, 53.4]
]);
При сложных приложениях важно управлять состоянием карты централизованно:
Пример сериализации состояния:
const state = {
center: map.getCenter(),
zoom: map.getZoom()
};
Mapbox GL JS часто используется как визуальный слой поверх:
Типичный паттерн — сервер отдаёт GeoJSON, клиент отображает:
fetch('/api/points')
.then(res => res.json())
.then(data => {
map.getSource('points').setData(data);
});
Это позволяет отделить геообработку от визуализации и масштабировать архитектуру приложения.