Стилизация draw-объектов в MapLibre GL JS строится вокруг стандартного механизма слоёв стиля и геообъектов GeoJSON, которые динамически добавляются и обновляются библиотекой рисования (обычно через совместимый пакет MapLibre Draw, основанный на Mapbox GL Draw). Визуальное представление геометрий определяется не самим инструментом рисования, а набором слоёв, фильтров и выражений стиля, которые привязываются к источнику данных draw.
Основная идея заключается в том, что все создаваемые пользователем объекты попадают в единый GeoJSON source, после чего отображаются через несколько специализированных слоёв: линии, полигоны и точки. Каждый слой отвечает за свой тип геометрии и может иметь отдельную стилизацию для состояний объекта (обычный, выделенный, редактируемый, активный вершиной).
При подключении инструмента рисования создаётся источник данных вида:
единый GeoJSON source (например,
mapbox-gl-draw-cold)
набор слоёв:
Каждый слой использует фильтрацию по свойствам feature, которые инструмент добавляет автоматически:
active: активен ли объектmode: режим редактированияmeta: тип служебной геометрии (vertex, midPoint и
т.д.)id: идентификатор объектаПример базовой структуры слоя:
map.addLayer({
id: 'gl-draw-polygon-fill',
type: 'fill',
source: 'mapbox-gl-draw-cold',
filter: ['all', ['==', '$type', 'Polygon']],
paint: {
'fill-color': '#3bb2d0',
'fill-opacity': 0.4
}
});
Полигональные draw-объекты обычно визуализируются через два слоя:
fill — заливкаline — контурСтилизация fill слоя:
'fill-color': [
'case',
['boolean', ['feature-state', 'active'], false],
'#ff6b6b',
'#3bb2d0'
],
'fill-opacity': 0.4
Контур:
'line-color': '#1f6feb',
'line-width': 2
Использование feature-state позволяет динамически менять
стиль без перезагрузки источника данных.
Линии используют тип слоя line и часто стилизуются через
ширину и цвет:
map.addLayer({
id: 'gl-draw-line',
type: 'line',
source: 'mapbox-gl-draw-cold',
filter: ['all', ['==', '$type', 'LineString']],
paint: {
'line-color': [
'case',
['boolean', ['feature-state', 'active'], false],
'#ff9800',
'#4caf50'
],
'line-width': 3
}
});
Дополнительно можно использовать:
line-dasharray для пунктирных линийТочки используются для:
map.addLayer({
id: 'gl-draw-point',
type: 'circle',
source: 'mapbox-gl-draw-cold',
filter: ['all', ['==', '$type', 'Point']],
paint: {
'circle-radius': 5,
'circle-color': [
'case',
['boolean', ['feature-state', 'active'], false],
'#e91e63',
'#2196f3'
],
'circle-stroke-width': 1,
'circle-stroke-color': '#ffffff'
}
});
Механизм feature-state является ключевым инструментом
динамической стилизации draw-объектов. Он позволяет изменять внешний вид
без изменения GeoJSON.
Основные состояния:
active — объект выбранhover — наведён курсорselectedVertex — активная вершинаПример установки состояния:
map.setFeatureState(
{ source: 'mapbox-gl-draw-cold', id: featureId },
{ active: true }
);
Стили на основе состояния:
'fill-opacity': [
'case',
['boolean', ['feature-state', 'active'], false],
0.7,
0.3
]
Draw-инструменты часто используют два источника:
...-cold — стабильные объекты...-hot — редактируемые состоянияCold слой отвечает за сохранённые геометрии, hot — за текущие изменения.
Пример фильтрации:
filter: ['all', ['!=', 'mode', 'static']]
Такое разделение позволяет минимизировать перерисовку и повысить производительность при редактировании.
Особое внимание уделяется вершинам полигонов:
vertex)midpoint)Фильтрация:
filter: ['all', ['==', 'meta', 'vertex']]
Стилизация вершин:
'circle-radius': 4,
'circle-color': '#ffffff',
'circle-stroke-color': '#000000',
'circle-stroke-width': 2
Midpoints часто визуализируются более прозрачно:
'circle-opacity': 0.5
При инициализации draw-инструмента можно полностью переопределить стили:
const draw = new MapboxDraw({
styles: [
{
id: 'gl-draw-polygon-fill',
type: 'fill',
filter: ['all', ['==', '$type', 'Polygon']],
paint: {
'fill-color': '#2ecc71',
'fill-opacity': 0.5
}
},
{
id: 'gl-draw-line',
type: 'line',
filter: ['all', ['==', '$type', 'LineString']],
paint: {
'line-color': '#27ae60',
'line-width': 3
}
}
]
});
Это позволяет полностью заменить стандартную визуализацию.
Zoom-dependent стили важны для масштабируемости отображения:
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
5, 2,
10, 4,
15, 8
]
Контуры также могут усиливаться при увеличении масштаба:
'line-width': [
'interpolate',
['linear'],
['zoom'],
10, 1,
16, 4
]
MapLibre GL JS поддерживает expression-based стили, позволяющие комбинировать условия:
'fill-color': [
'case',
['all',
['boolean', ['feature-state', 'active'], false],
['==', ['get', 'type'], 'restricted']
],
'#e74c3c',
'#3498db'
]
Это позволяет реализовывать:
Draw-объекты могут содержать пользовательские свойства:
draw.add({
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [...]
},
properties: {
category: 'zone',
priority: 3
}
});
Стилизация по свойствам:
'fill-color': [
'match',
['get', 'category'],
'zone', '#8e44ad',
'restricted', '#c0392b',
'#2980b9'
]
Важно учитывать порядок слоёв:
Неправильная последовательность приводит к перекрытию интерактивных элементов.
Для сложных сцен применяются:
Также важно избегать избыточных setFeatureState вызовов
в циклах, так как они приводят к деградации производительности при
большом количестве объектов.
Стилизация draw-элементов напрямую связана с UX взаимодействия:
Пример hover:
'line-color': [
'case',
['boolean', ['feature-state', 'hover'], false],
'#f1c40f',
'#2c3e50'
]
Draw-слои могут визуально интегрироваться с основным стилем карты:
Пример адаптации:
'fill-color': [
'interpolate',
['linear'],
['zoom'],
0, '#5dade2',
10, '#2e86c1',
15, '#1b4f72'
]