Слои в Mapbox GL JS являются ключевым механизмом визуализации геоданных. Именно слои определяют, как данные из источников (sources) отображаются на карте: в виде линий, полигонов, точек, растровых тайлов или 3D-объектов. Архитектура слоёв строится вокруг декларативного описания стиля, где каждый слой представляет собой независимую единицу рендеринга с собственными параметрами отображения и правилами фильтрации данных.
Mapbox GL JS поддерживает несколько базовых типов слоёв, каждый из которых предназначен для определённого вида визуализации.
fill — отображение полигонов с заливкой. Используется для административных границ, зон, территорий.
line — линии и контуры. Подходит для дорог, маршрутов, границ.
symbol — текстовые и иконографические маркеры. Используется для POI, подписей, меток.
circle — точечные данные в виде окружностей. Часто применяется для кластеризации или визуализации плотности.
raster — растровые тайлы, например спутниковые снимки.
fill-extrusion — 3D-экструзия полигонов. Используется для визуализации зданий.
heatmap — тепловые карты плотности данных.
hillshade — визуализация рельефа.
Каждый тип слоя имеет собственный набор свойств в секциях layout и paint, что определяет поведение слоя на уровне геометрии и визуального оформления.
Основной способ создания слоя — метод addLayer.
map.addLayer({
id: 'roads',
type: 'line',
source: 'streets',
'source-layer': 'road',
paint: {
'line-color': '#ff0000',
'line-width': 2
}
});
Каждый слой обязан иметь уникальный id. Параметр
source указывает на источник данных, который должен быть
заранее добавлен через addSource. Векторные тайлы требуют
указания source-layer, определяющего конкретный слой внутри
тайлового набора.
Порядок добавления влияет на порядок отрисовки: последние добавленные слои отображаются выше предыдущих.
Порядок слоёв определяет визуальную иерархию. Mapbox GL JS использует стековую модель рендеринга: каждый новый слой добавляется поверх существующих.
map.addLayer({
id: 'water-outline',
type: 'line',
source: 'water',
paint: {
'line-color': '#0000ff'
}
}, 'road-label');
Второй аргумент addLayer задаёт beforeId,
то есть слой, перед которым будет вставлен новый.
map.moveLayer('roads', 'water');
Метод moveLayer изменяет порядок существующего слоя,
перемещая его выше или ниже указанного слоя.
Если второй аргумент не указан, слой перемещается наверх стека.
const layer = map.getLayer('roads');
Метод возвращает объект описания слоя, включая его тип, источник и стили.
Видимость слоя управляется через layout.visibility.
map.setLayoutProperty('roads', 'visibility', 'none');
Доступные значения:
visible — слой отображаетсяnone — слой скрытЭто позволяет быстро переключать визуальные режимы без удаления слоя.
Слои разделяют свойства на две категории: layout и paint.
map.setPaintProperty('roads', 'line-color', '#00ff00');
map.setPaintProperty('roads', 'line-width', 4);
map.setLayoutProperty('roads', 'line-cap', 'round');
Изменения применяются динамически без пересоздания слоя.
Фильтры позволяют ограничить отображаемые объекты внутри слоя на основе их атрибутов.
map.setFilter('roads', ['==', 'type', 'highway']);
Фильтры используют выражения Mapbox Expression API и поддерживают логические операции:
map.setFilter('roads', [
'all',
['==', 'type', 'highway'],
['>=', 'lanes', 2]
]);
Фильтрация применяется на уровне рендеринга, не изменяя исходные данные источника.
map.removeLayer('roads');
Удаление слоя не затрагивает источник данных. Один источник может использоваться несколькими слоями одновременно.
Каждый слой связан с источником через параметр source.
Источники бывают нескольких типов:
Пример GeoJSON-источника:
map.addSource('points', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: []
}
});
Слой, использующий этот источник:
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points',
paint: {
'circle-radius': 6,
'circle-color': '#ff0000'
}
});
Слои поддерживают выражения, позволяющие динамически изменять стили в зависимости от данных.
map.addLayer({
id: 'population',
type: 'circle',
source: 'cities',
paint: {
'circle-radius': [
'interpolate',
['linear'],
['get', 'population'],
1000, 4,
1000000, 20
],
'circle-color': [
'step',
['get', 'population'],
'#00ff00',
100000,
'#ffff00',
500000,
'#ff0000'
]
}
});
Выражения позволяют строить сложные визуальные правила без внешней логики JavaScript.
Прозрачность регулируется через свойства paint:
map.setPaintProperty('water', 'fill-opacity', 0.5);
Для линий:
map.setPaintProperty('roads', 'line-opacity', 0.3);
Для символов:
map.setPaintProperty('labels', 'text-opacity', 0.8);
Слой symbol обладает механизмом разрешения конфликтов
подписи. Он управляет пересечением текста и иконок.
map.addLayer({
id: 'labels',
type: 'symbol',
source: 'places',
layout: {
'text-field': ['get', 'name'],
'text-size': 12,
'text-allow-overlap': false,
'text-ignore-placement': false
}
});
Ключевые параметры:
text-allow-overlap — разрешение наложения текстаicon-allow-overlap — разрешение наложения иконокsymbol-sort-key — приоритет отображенияMapbox GL JS позволяет изменять свойства слоя без перерисовки всей карты.
function highlightRoads(enabled) {
map.setPaintProperty(
'roads',
'line-color',
enabled ? '#ff0000' : '#888888'
);
}
Изменения применяются мгновенно благодаря WebGL-рендереру.
Один источник может быть использован несколькими слоями для создания сложных эффектов.
map.addLayer({
id: 'road-base',
type: 'line',
source: 'roads',
paint: {
'line-color': '#333',
'line-width': 6
}
});
map.addLayer({
id: 'road-outline',
type: 'line',
source: 'roads',
paint: {
'line-color': '#fff',
'line-width': 2
}
});
Такой подход позволяет создавать обводки, тени и многослойные визуальные эффекты.
В отличие от CSS, Mapbox GL JS не использует явный z-index. Порядок определяется положением слоя в стиле.
Стек слоёв можно рассматривать как массив:
Перестановка слоёв напрямую влияет на визуальную композицию карты.
Слои рендерятся через WebGL, поэтому изменения свойств проходят через GPU-пайплайн. Частое обновление свойств:
setPaintPropertyИспользование выражений вместо JavaScript-логики снижает нагрузку на основной поток.
Слои участвуют в событиях карты:
map.on('click', 'roads', (e) => {
console.log(e.features);
});
Hover-состояния:
map.on('mousemove', 'roads', (e) => {
map.setPaintProperty('roads', 'line-color', '#ff9900');
});
Слои могут быть как интерактивными, так и чисто визуальными.
Фильтры часто применяются для подсветки объектов:
map.setFilter('roads', [
'!=',
['get', 'id'],
selectedId
]);
Такой подход позволяет скрывать или выделять элементы без изменения источника данных.