В библиотеке Mapbox GL JS основой всей работы выступает экземпляр
карты, создаваемый через конструктор mapboxgl.Map. Именно
этот объект становится контейнером для всех последующих сущностей:
источников данных, слоёв, маркеров, изображений и пользовательских
компонентов.
Создание карты требует минимального набора параметров: контейнера, стиля, центра и масштаба.
mapboxgl.accessToken = 'YOUR_ACCESS_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [37.6173, 55.7558],
zoom: 10
});
После инициализации формируется объектная модель карты, в которую встраиваются все последующие элементы. Архитектура Mapbox GL JS основана на декларативном описании слоёв и источников данных, где каждый объект имеет собственный жизненный цикл и обновляется независимо.
Источники данных представляют собой фундамент визуализации. Они определяют, откуда поступает информация для отображения на карте. Основной формат — GeoJSON, хотя поддерживаются и тайловые источники.
Добавление источника выполняется через метод
addSource.
map.on('load', () => {
map.addSource('points-source', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [37.6173, 55.7558]
},
properties: {
title: 'Центральная точка'
}
}
]
}
});
});
Каждый источник представляет собой независимый объект внутри
состояния карты. При изменении данных через setData
происходит автоматическое обновление всех связанных слоёв.
const source = map.getSource('points-source');
source.setData({
type: 'FeatureCollection',
features: []
});
Ключевой принцип заключается в разделении данных и визуализации: источник не содержит информации о внешнем виде, он отвечает только за структуру и геометрию.
Слои отвечают за отображение данных, поступающих из источников. Каждый слой привязан к конкретному source и определяет способ визуализации: точки, линии, полигоны, текст или растровые данные.
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points-source',
paint: {
'circle-radius': 8,
'circle-color': '#ff0000'
}
});
Тип слоя определяет набор доступных свойств:
circle — отображение точекline — линии и маршрутыfill — полигоныsymbol — текст и иконкиheatmap — тепловые картыСлои формируют стек отрисовки. Порядок добавления влияет на
визуальную иерархию. Управление порядком осуществляется через
beforeId.
map.addLayer(layerConfig, 'waterway-label');
Маркер представляет собой DOM-объект, закреплённый за координатами карты. В отличие от слоёв, маркеры не используют WebGL-рендеринг и могут содержать произвольную HTML-разметку.
const marker = new mapboxgl.Marker()
.setLngLat([37.6173, 55.7558])
.addTo(map);
Поддерживается создание пользовательских маркеров через DOM-элемент:
const el = document.createElement('div');
el.className = 'custom-marker';
const marker = new mapboxgl.Marker(el)
.setLngLat([37.6, 55.7])
.addTo(map);
Маркер может быть связан с событиями и динамически обновляться:
marker.setLngLat([37.62, 55.76]);
При увеличении количества маркеров снижается производительность, так как каждый объект существует как отдельный DOM-узел.
Popup является привязанным к координате объектом интерфейса, отображающим информацию поверх карты.
const popup = new mapboxgl.Popup()
.setLngLat([37.6173, 55.7558])
.setHTML('<h3>Объект</h3><p>Описание точки</p>')
.addTo(map);
Popup может быть привязан к маркеру:
marker.setPopup(popup);
Основные параметры управления поведением:
closeButtoncloseOnClickoffsetPopup создаёт отдельный слой DOM, который управляется независимо от WebGL-сцены.
Для symbol-слоёв часто требуется регистрация изображений в стиле
карты. Изображения добавляются в стиль через addImage.
map.on('load', () => {
map.loadImage('icon.png', (error, image) => {
if (error) throw error;
map.addImage('custom-icon', image);
map.addLayer({
id: 'symbols',
type: 'symbol',
source: 'points-source',
layout: {
'icon-image': 'custom-icon',
'icon-size': 1
}
});
});
});
Изображение становится глобальным ресурсом стиля и может использоваться в нескольких слоях одновременно.
GeoJSON выступает стандартным способом описания геометрии. В рамках Mapbox GL JS он используется для точек, линий и полигонов.
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [37.6173, 55.7558]
}
}
{
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [
[37.61, 55.75],
[37.62, 55.76]
]
}
}
{
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[
[37.61, 55.75],
[37.62, 55.75],
[37.62, 55.76],
[37.61, 55.76],
[37.61, 55.75]
]]
}
}
Структура GeoJSON определяет не только геометрию, но и свойства, используемые в стилизации:
properties: {
name: 'Объект',
category: 'important'
}
Динамическое поведение достигается через обновление источников в реальном времени. Это применяется при отображении движущихся объектов, трекинга и аналитических систем.
setInterval(() => {
const source = map.getSource('points-source');
source.setData({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
37.6173 + Math.random() * 0.01,
55.7558 + Math.random() * 0.01
]
}
}
]
});
}, 1000);
Обновление данных автоматически вызывает перерасчёт всех зависимых слоёв без необходимости ручного перерендера.
Mapbox GL JS поддерживает трёхмерную визуализацию через
fill-extrusion слой.
map.addLayer({
id: 'buildings',
source: 'composite',
'source-layer': 'building',
type: 'fill-extrusion',
paint: {
'fill-extrusion-color': '#aaa',
'fill-extrusion-height': ['get', 'height'],
'fill-extrusion-base': ['get', 'min_height'],
'fill-extrusion-opacity': 0.6
}
});
Высота объектов извлекается из атрибутов данных, что позволяет строить реалистичные 3D сцены городской застройки.
Контролы расширяют функциональность карты и создаются как объекты с
методами onAdd и onRemove.
class CustomControl {
onAdd(map) {
this._map = map;
this._container = document.createElement('div');
this._container.className = 'custom-control';
this._container.innerText = 'Control';
return this._container;
}
onRemove() {
this._container.parentNode.removeChild(this._container);
this._map = undefined;
}
}
map.addControl(new CustomControl());
Контрол становится частью интерфейса карты и управляется через жизненный цикл Mapbox.
Анимация реализуется через обновление координат или параметров слоя в
цикле requestAnimationFrame.
function animate() {
const source = map.getSource('points-source');
const time = Date.now() * 0.001;
source.setData({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
37.6173 + Math.sin(time) * 0.01,
55.7558 + Math.cos(time) * 0.01
]
}
}
]
});
requestAnimationFrame(animate);
}
animate();
Подобный подход используется для визуализации движения транспорта, потоков данных и интерактивных симуляций.
Каждый объект карты может быть связан с событиями: кликом, наведением, перемещением.
map.on('click', 'points-layer', (e) => {
const feature = e.features[0];
new mapboxgl.Popup()
.setLngLat(feature.geometry.coordinates)
.setHTML(feature.properties.title)
.addTo(map);
});
События работают на уровне слоёв, что позволяет обрабатывать большое количество объектов без привязки к DOM.
Сложные визуализации формируются через комбинацию источников, слоёв и интерфейсных объектов. Например, кластеризация точек:
map.addSource('clusters', {
type: 'geojson',
data: geojsonData,
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
Отображение кластеров требует нескольких слоёв: для самих кластеров, их числовых значений и отдельных точек.
Слои могут зависеть от условий данных через выражения:
paint: {
'circle-color': [
'case',
['==', ['get', 'category'], 'important'],
'#ff0000',
'#0000ff'
]
}
Так формируются динамические стили, реагирующие на свойства объектов.
Стиль карты в Mapbox GL JS представляет собой JSON-структуру, содержащую:
Каждый элемент стиля является объектом с собственной конфигурацией и идентификатором. Управление стилем позволяет централизованно изменять поведение всей карты без изменения логики приложения.
Объекты карты создаются, изменяются и удаляются через API экземпляра карты.
Удаление слоя:
map.removeLayer('points-layer');
Удаление источника:
map.removeSource('points-source');
Удаление изображения:
map.removeImage('custom-icon');
Корректное управление жизненным циклом предотвращает утечки памяти и снижает нагрузку на WebGL контекст.