В Mapbox GL JS визуальные объекты на карте могут быть реализованы двумя принципиально разными подходами: через HTML-элементы (Marker, Popup и кастомные DOM-слои) либо через встроенные слои рендеринга WebGL. Одним из ключевых инструментов нативного отображения данных является symbol layer, который позволяет полностью отказаться от HTML-представления объектов и перенести их рендеринг в графический конвейер карты.
HTML-подход в Mapbox GL JS основан на создании DOM-элементов, которые позиционируются поверх карты. Каждый маркер или пользовательский элемент существует как отдельный узел DOM, который обновляется при перемещении карты. Это удобно для небольшого количества объектов, но становится узким местом при масштабировании.
Проблемы DOM-меток:
Symbol layer работает иначе: все точки данных передаются в GPU через WebGL, где отрисовка происходит как часть единого слоя. Это исключает необходимость работы с DOM для каждого объекта.
Symbol layer — это тип слоя в Mapbox GL JS, предназначенный для
отображения иконок и текстовых меток на основе
геометрии типа Point. Он использует заранее подготовленные
спрайты или SDF-иконки, а также текстовые рендеры через шрифты,
встроенные в стиль карты.
Основные возможности:
Symbol layer добавляется в стиль карты как часть слоёв:
map.addLayer({
id: 'points',
type: 'symbol',
source: 'places',
layout: {
'icon-image': 'marker-15',
'text-field': ['get', 'title'],
'text-offset': [0, 1.2],
'text-anchor': 'top'
}
});
Источник данных при этом обычно представляет собой GeoJSON:
map.addSource('places', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [76.8897, 43.2389]
},
properties: {
title: 'Объект A'
}
}
]
}
});
В отличие от HTML-маркеров, данные полностью декларативны и не требуют ручного создания DOM-узлов.
Symbol layer обрабатывается как часть WebGL сцены. Все объекты проходят через единый пайплайн:
Благодаря этому достигается высокая производительность даже при десятках тысяч точек.
Ключевое отличие: нет индивидуального обновления объектов. Любое изменение слоя приводит к перерасчёту всего батча, а не отдельных элементов.
Иконки в symbol layer основаны на sprite sheet, который описывается в стиле карты:
map.addImage('custom-marker', imageData, {
sdf: true
});
Использование в слое:
layout: {
'icon-image': 'custom-marker',
'icon-size': 1.2
}
Особенность SDF (Signed Distance Field) заключается в том, что иконки становятся масштабируемыми и могут менять цвет без перерисовки изображения.
Text rendering в symbol layer использует glyph atlas. Шрифты загружаются заранее:
map.addLayer({
id: 'labels',
type: 'symbol',
source: 'places',
layout: {
'text-field': ['get', 'name'],
'text-font': ['Open Sans Regular', 'Arial Unicode MS Regular'],
'text-size': 14
}
});
Поддерживаются выражения Mapbox GL JS, что позволяет динамически формировать текст:
'text-field': ['concat', ['get', 'city'], ', ', ['get', 'country']]
Одно из ключевых преимуществ symbol layer — управление видимостью без DOM-логики.
layout: {
'icon-size': [
'interpolate',
['linear'],
['zoom'],
5, 0.5,
15, 1.5
]
}
Также можно управлять появлением текста:
'text-opacity': [
'step',
['zoom'],
0,
10,
1
]
Это позволяет строить адаптивные карты без дополнительных вычислений на стороне JavaScript.
Symbol layer поддерживает фильтры на уровне GPU-пайплайна:
filter: ['==', ['get', 'type'], 'restaurant']
Фильтрация выполняется до рендеринга, что делает её значительно быстрее, чем скрытие HTML-элементов через CSS или JS.
При работе с большим количеством точек используется кластеризация:
map.addSource('points', {
type: 'geojson',
data: geojsonData,
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
Symbol layer затем отображает как кластеры, так и отдельные точки:
map.addLayer({
id: 'clusters',
type: 'symbol',
source: 'points',
filter: ['has', 'point_count'],
layout: {
'text-field': ['get', 'point_count'],
'icon-image': 'cluster-icon'
}
});
Несмотря на высокую производительность, symbol layer имеет ряд ограничений:
В случаях, когда требуется сложная интерактивная визуализация, HTML-слои остаются единственным вариантом.
Symbol layer обеспечивает:
HTML-метки обеспечивают:
Выбор подхода определяется балансом между визуальной гибкостью и производительностью, при этом symbol layer является базовым инструментом для любых высоконагруженных картографических систем на Mapbox GL JS.