Стилизация полигонов в OpenLayers реализуется через систему стилей,
основанную на объектах ol/style/Style, которые применяются
к геометрии слоя и позволяют управлять внешним видом заливки, обводки и
дополнительной графики, связанной с полигональными объектами.
Основой стилизации выступает комбинация трёх ключевых классов:
Fill — отвечает за заливку области полигонаStroke — управляет контуромStyle — объединяет параметры и применяется к
объектуimport Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
const polygonStyle = new Style({
fill: new Fill({
color: 'rgba(0, 150, 255, 0.4)'
}),
stroke: new Stroke({
color: '#1f4e79',
width: 2
})
});
Такой стиль применяется ко всем полигонам слоя одинаково и является статическим вариантом оформления.
Стилизация задаётся через свойство style у
VectorLayer:
import VectorLayer from 'ol/layer/Vector';
const layer = new VectorLayer({
source: vectorSource,
style: polygonStyle
});
В этом случае каждый объект слоя получает одинаковый визуальный вид, независимо от его атрибутов.
Для более гибкого управления используется функция стиля, принимающая feature и текущий масштабный уровень.
const styleFunction = function (feature, resolution) {
return new Style({
fill: new Fill({
color: feature.get('color') || 'rgba(0, 150, 255, 0.3)'
}),
stroke: new Stroke({
color: '#333',
width: resolution < 10 ? 3 : 1
})
});
};
layer.setStyle(styleFunction);
Здесь важны два механизма:
feature.get() позволяет извлекать атрибуты
геометрииresolution отражает текущий масштаб картыЭто позволяет изменять внешний вид полигона в зависимости от данных или уровня приближения.
Заливка полигона задаётся через RGBA или HEX с прозрачностью.
fill: new Fill({
color: 'rgba(255, 0, 0, 0.2)'
})
Полупрозрачность используется для отображения перекрывающихся областей, тепловых карт и административных границ.
OpenLayers не предоставляет встроенных градиентов в
Fill, но поддерживает использование canvas-объектов:
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const gradient = context.createLinearGradient(0, 0, 100, 100);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(1, 'red');
const style = new Style({
fill: new Fill({
color: gradient
})
});
Такой подход используется при визуализации интенсивностей или статистических показателей.
Контур задаётся через Stroke, где важны:
stroke: new Stroke({
color: '#000',
width: 2,
lineDash: [4, 6],
lineJoin: 'round'
})
Пунктирные линии часто применяются для обозначения временных или условных границ.
Часто полигоны содержат свойства, определяющие их внешний вид:
const styleFunction = (feature) => {
const type = feature.get('type');
const colors = {
forest: 'rgba(34, 139, 34, 0.4)',
water: 'rgba(0, 0, 255, 0.3)',
urban: 'rgba(128, 128, 128, 0.3)'
};
return new Style({
fill: new Fill({
color: colors[type] || 'rgba(200, 200, 200, 0.3)'
}),
stroke: new Stroke({
color: '#222',
width: 1
})
});
};
Такой подход формирует правило-ориентированную картографическую визуализацию.
Разрешение карты влияет на детализацию отображения:
const styleFunction = (feature, resolution) => {
const visible = resolution < 50;
return new Style({
fill: new Fill({
color: 'rgba(0, 0, 255, 0.2)'
}),
stroke: new Stroke({
color: '#003366',
width: visible ? 2 : 0
})
});
};
При уменьшении масштаба можно скрывать обводку или упрощать визуализацию.
Создание новых объектов стиля на каждый рендер снижает производительность. Оптимизация достигается через кеширование:
const styleCache = {};
const styleFunction = (feature) => {
const key = feature.get('type');
if (!styleCache[key]) {
styleCache[key] = new Style({
fill: new Fill({
color: key === 'water'
? 'rgba(0, 0, 255, 0.3)'
: 'rgba(0, 255, 0, 0.3)'
}),
stroke: new Stroke({
color: '#333',
width: 1
})
});
}
return styleCache[key];
};
Такой подход особенно важен при работе с тысячами полигонов.
Один объект может иметь несколько визуальных слоёв оформления:
const style = [
new Style({
stroke: new Stroke({
color: '#000',
width: 3
})
}),
new Style({
fill: new Fill({
color: 'rgba(255, 255, 0, 0.3)'
})
})
];
Первый стиль отвечает за контур, второй — за заливку. Такой подход используется для сложных эффектов.
Помимо заливки цветом возможно использование паттернов:
const pattern = new Fill({
color: 'rgba(0,0,0,0)',
// canvas pattern может быть задан через createPattern
});
Через canvas можно задать текстуру:
const img = new Image();
img.src = 'pattern.png';
img.onl oad = function () {
const patternCanvas = document.createElement('canvas');
const ctx = patternCanvas.getContext('2d');
const pattern = ctx.createPattern(img, 'repeat');
const style = new Style({
fill: new Fill({
color: pattern
})
});
};
Площадь или форма полигона может влиять на стиль:
const styleFunction = (feature) => {
const geometry = feature.getGeometry();
const area = geometry.getArea();
return new Style({
fill: new Fill({
color: area > 1000000
? 'rgba(255, 0, 0, 0.4)'
: 'rgba(0, 255, 0, 0.4)'
}),
stroke: new Stroke({
color: '#000',
width: 1
})
});
};
Такой метод применяется в тематических картах.
При комбинировании условий учитываются сразу несколько факторов:
const styleFunction = (feature, resolution) => {
const status = feature.get('status');
const area = feature.getGeometry().getArea();
let fillColor = 'rgba(200,200,200,0.3)';
if (status === 'active' && area > 500000) {
fillColor = 'rgba(255,0,0,0.4)';
} else if (status === 'active') {
fillColor = 'rgba(255,165,0,0.3)';
}
return new Style({
fill: new Fill({ color: fillColor }),
stroke: new Stroke({
color: '#111',
width: resolution < 20 ? 2 : 1
})
});
};
Когда полигоны накладываются друг на друга, визуальное восприятие зависит от:
new Style({
zIndex: 10,
fill: new Fill({
color: 'rgba(0,0,255,0.3)'
})
});
Более высокий zIndex поднимает объект выше в
отрисовке.
Для крупных проектов стили выносятся в отдельные модули:
export function getPolygonStyle(feature, resolution) {
return new Style({
fill: new Fill({
color: feature.get('color')
}),
stroke: new Stroke({
color: '#444',
width: 1
})
});
}
Такой подход упрощает сопровождение и масштабирование кода.