Полигональная геометрия в MapLibre GL JS основана на стандарте
GeoJSON, где объект типа Polygon представляет замкнутую
область на поверхности карты. Координаты задаются в порядке
[долгота, широта], что критически важно для корректного
отображения.
Базовая структура полигона:
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[30.31413, 59.93863],
[30.32000, 59.93863],
[30.32000, 59.94200],
[30.31413, 59.94200],
[30.31413, 59.93863]
]
]
},
"properties": {}
}
Первый элемент массива координат — внешний контур. Последняя точка должна совпадать с первой, формируя замкнутую область.
Polygon может содержать отверстия, задаваемые внутренними кольцами. Они добавляются как дополнительные массивы координат внутри основного массива:
{
"type": "Polygon",
"coordinates": [
[
[30.30, 59.93],
[30.33, 59.93],
[30.33, 59.95],
[30.30, 59.95],
[30.30, 59.93]
],
[
[30.31, 59.935],
[30.32, 59.935],
[30.32, 59.945],
[30.31, 59.945],
[30.31, 59.935]
]
]
}
Первое кольцо — внешний контур, последующие — вырезы.
Для представления нескольких независимых областей используется тип
MultiPolygon:
{
"type": "MultiPolygon",
"coordinates": [
[
[
[30.1, 59.9],
[30.2, 59.9],
[30.2, 60.0],
[30.1, 60.0],
[30.1, 59.9]
]
],
[
[
[30.3, 59.9],
[30.4, 59.9],
[30.4, 60.0],
[30.3, 60.0],
[30.3, 59.9]
]
]
]
}
Каждый полигон внутри массива полностью независим.
Полигональная геометрия отображается через source типа
geojson и слой fill.
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [30.31, 59.94],
zoom: 12
});
map.on('load', () => {
map.addSource('area', {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [
[
[30.30, 59.93],
[30.33, 59.93],
[30.33, 59.95],
[30.30, 59.95],
[30.30, 59.93]
]
]
}
}
});
map.addLayer({
id: 'area-fill',
type: 'fill',
source: 'area',
paint: {
'fill-color': '#3b82f6',
'fill-opacity': 0.5
}
});
});
Ключевой слой для полигона — fill. Он отвечает за
заливку области.
Для визуального выделения границ используется отдельный слой типа
line.
map.addLayer({
id: 'area-outline',
type: 'line',
source: 'area',
paint: {
'line-color': '#1e3a8a',
'line-width': 2
}
});
Разделение fill и line слоёв — стандартная практика, позволяющая независимо управлять заливкой и контуром.
MapLibre GL JS поддерживает 3D-экструзию через слой
fill-extrusion, где полигон «выдавливается» в
пространство.
map.addLayer({
id: 'area-3d',
type: 'fill-extrusion',
source: 'area',
paint: {
'fill-extrusion-color': '#10b981',
'fill-extrusion-height': 200,
'fill-extrusion-opacity': 0.7
}
});
Высота может быть статической или вычисляться через выражения:
'fill-extrusion-height': ['get', 'height']
Направление обхода координат влияет на интерпретацию внешних и внутренних колец.
Некорректный порядок может привести к:
MapLibre частично нормализует winding order, но полагаться на это не рекомендуется.
GeoJSON-источник можно динамически изменять через
setData.
const source = map.getSource('area');
source.setData({
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [
[
[30.31, 59.94],
[30.34, 59.94],
[30.34, 59.96],
[30.31, 59.96],
[30.31, 59.94]
]
]
}
});
Это основной механизм интерактивного редактирования геометрии.
MapLibre GL JS поддерживает data-driven styling, позволяющий менять внешний вид полигона в зависимости от свойств.
'fill-color': [
'case',
['>', ['get', 'population'], 1000],
'#ef4444',
'#3b82f6'
]
Возможные подходы:
Пример градиентной заливки:
'fill-color': [
'interpolate',
['linear'],
['get', 'value'],
0, '#dbeafe',
100, '#60a5fa',
200, '#1d4ed8'
]
Полигоны чувствительны к порядку слоёв:
beforeIdmap.addLayer(layer, 'road-label');
Это позволяет контролировать визуальную иерархию.
map.on('click', 'area-fill', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['area-fill']
});
console.log(features[0].properties);
});
map.on('mousemove', 'area-fill', () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'area-fill', () => {
map.getCanvas().style.cursor = '';
});
Если источник содержит множество объектов, используется фильтрация на уровне слоя:
'filter': ['==', ['get', 'type'], 'active']
Это позволяет динамически отображать подмножество геометрий без изменения источника данных.
Полигональные данные могут стать узким местом при высокой сложности геометрии.
Основные ограничения:
setDataПрактические оптимизации:
Снижение детализации:
упрощение геометрии (Douglas-Peucker)
Разбиение на тайлы:
vector tiles вместо GeoJSONОграничение перерисовок:
[lat, lng] вместо [lng, lat]
Приводит к смещению объекта в неверную точку мира.
Последняя точка должна повторять первую.
Внутренние полигоны должны находиться строго внутри внешнего.
Тысячи вершин могут замедлить рендеринг и взаимодействие.
Polygon часто хранит бизнес-данные:
"properties": {
"name": "Industrial zone",
"status": "active",
"priority": 3
}
Эти данные используются:
Polygon редко используется изолированно. Типичная связка:
fill — заливка территорииline — границаsymbol — подписьcircle — маркеры внутри областиЭто позволяет строить многоуровневые карты территорий, зон и регионов.