Объект Style в OpenLayers отвечает за визуальное
оформление географических объектов на карте. Именно через него
определяется внешний вид точек, линий, полигонов, подписей и значков.
Каждый векторный объект может иметь собственный стиль или использовать
общий стиль слоя.
Модуль расположен в пакете:
import Style from 'ol/style/Style.js';
Объект Style выступает контейнером для других стилевых
компонентов:
Fill — заливка полигонов;Stroke — обводка линий и границ;Circle — отображение точек в виде окружностей;Icon — отображение изображений;Text — подписи;RegularShape — геометрические маркеры;ImageStyle — базовый класс для графических
символов.Стиль применяется как к отдельным объектам (Feature),
так и к целым слоям (VectorLayer).
Наиболее распространённый вариант — создание объекта
Style с настройкой заливки и контура.
import Style from 'ol/style/Style.js';
import Fill from 'ol/style/Fill.js';
import Stroke from 'ol/style/Stroke.js';
const polygonStyle = new Style({
fill: new Fill({
color: 'rgba(0, 0, 255, 0.3)'
}),
stroke: new Stroke({
color: '#0000ff',
width: 2
})
});
В результате:
Чаще всего стиль задаётся непосредственно слою.
import VectorLayer from 'ol/layer/Vector.js';
const vectorLayer = new VectorLayer({
source: vectorSource,
style: polygonStyle
});
После этого все объекты слоя будут отображаться одинаково.
Каждый объект может иметь собственный стиль.
feature.setStyle(
new Style({
fill: new Fill({
color: 'yellow'
}),
stroke: new Stroke({
color: 'red',
width: 3
})
})
);
Если стиль задан объекту, он имеет приоритет над настройками слоя.
Конструктор принимает объект конфигурации:
const style = new Style({
fill: fillObject,
stroke: strokeObject,
image: imageObject,
text: textObject,
geometry: geometryObject,
zIndex: 10
});
Основные параметры:
| Параметр | Назначение |
|---|---|
fill |
Заливка |
stroke |
Контур |
image |
Символы для точек |
text |
Подписи |
geometry |
Альтернативная геометрия |
zIndex |
Порядок отрисовки |
Класс Fill отвечает за внутреннюю заливку полигонов.
import Fill from 'ol/style/Fill.js';
const fill = new Fill({
color: 'rgba(255,0,0,0.4)'
});
Допустимые форматы цвета:
'red'
'#ff0000'
'rgb(255,0,0)'
'rgba(255,0,0,0.5)'
Пример:
const style = new Style({
fill: new Fill({
color: 'rgba(50,150,255,0.5)'
})
});
Класс Stroke определяет параметры контура.
import Stroke from 'ol/style/Stroke.js';
const stroke = new Stroke({
color: '#0066ff',
width: 4
});
Основные свойства:
new Stroke({
color: '#ff0000',
width: 3,
lineCap: 'round',
lineJoin: 'round',
lineDash: [10, 5],
miterLimit: 10
});
Определяет форму концов линии.
lineCap: 'butt'
lineCap: 'round'
lineCap: 'square'
Определяет форму соединения сегментов.
lineJoin: 'round'
lineJoin: 'bevel'
lineJoin: 'miter'
Создаёт пунктир.
stroke: new Stroke({
color: 'black',
width: 2,
lineDash: [8, 4]
})
Результат:
Для отображения точек часто используется класс
Circle.
import CircleStyle from 'ol/style/Circle.js';
const pointStyle = new Style({
image: new CircleStyle({
radius: 8,
fill: new Fill({
color: 'green'
}),
stroke: new Stroke({
color: 'white',
width: 2
})
})
});
Настраиваемые параметры:
| Свойство | Описание |
|---|---|
radius |
Радиус |
fill |
Заливка |
stroke |
Контур |
scale |
Масштабирование |
rotation |
Поворот |
Для отображения пользовательских изображений применяется класс
Icon.
import Icon from 'ol/style/Icon.js';
const iconStyle = new Style({
image: new Icon({
src: 'marker.png'
})
});
Более сложный пример:
new Style({
image: new Icon({
src: 'pin.png',
scale: 0.7,
rotation: Math.PI / 4,
opacity: 0.8
})
});
Основные параметры:
| Свойство | Назначение |
|---|---|
src |
Путь к изображению |
scale |
Масштаб |
rotation |
Поворот |
opacity |
Прозрачность |
anchor |
Точка привязки |
anchorXUnits |
Единицы по X |
anchorYUnits |
Единицы по Y |
По умолчанию привязка происходит к верхнему левому углу изображения.
Чаще используется привязка к нижнему центру:
new Icon({
src: 'pin.png',
anchor: [0.5, 1]
});
Значения интерпретируются как:
[горизонталь, вертикаль]
Где:
0.5
соответствует центру по ширине, а
1
нижней границе изображения.
Класс Text отвечает за отображение подписей.
import Text from 'ol/style/Text.js';
const textStyle = new Style({
text: new Text({
text: 'Город'
})
});
Более полный вариант:
new Style({
text: new Text({
text: 'Москва',
font: '16px Arial',
fill: new Fill({
color: '#000'
}),
stroke: new Stroke({
color: '#fff',
width: 3
})
})
});
Белая обводка текста повышает читаемость на фоне карты.
Содержимое подписи.
text: 'Река Волга'
Настройка шрифта.
font: 'bold 14px Verdana'
Горизонтальное выравнивание.
textAlign: 'left'
textAlign: 'center'
textAlign: 'right'
Вертикальное выравнивание.
textBaseline: 'middle'
Смещение подписи.
offsetY: -20
Подпись будет расположена выше объекта.
Часто текст берётся из атрибутов объекта.
const styleFunction = function(feature) {
return new Style({
text: new Text({
text: feature.get('name')
})
});
};
Пример данных:
{
name: 'Караганда'
}
На карте появится соответствующая подпись.
Одним из наиболее мощных механизмов OpenLayers является использование функции стилей.
layer.setStyle(function(feature) {
const population = feature.get('population');
if (population > 1000000) {
return bigCityStyle;
}
return smallCityStyle;
});
Функция вызывается для каждого объекта при отрисовке.
Преимущества:
Пример окраски полигонов по площади.
layer.setStyle(function(feature) {
const area = feature.get('area');
if (area < 100) {
return greenStyle;
}
if (area < 500) {
return yellowStyle;
}
return redStyle;
});
Подобный подход широко применяется при построении тематических карт.
Функция может возвращать несколько стилей одновременно.
return [
fillStyle,
labelStyle
];
Либо:
const styles = [
polygonStyle,
borderStyle,
textStyle
];
return styles;
OpenLayers последовательно отрисует каждый стиль.
Это позволяет создавать сложные визуальные эффекты.
Параметр zIndex определяет порядок отображения.
new Style({
zIndex: 100
});
Чем больше значение, тем выше объект находится визуально.
Пример:
const roadStyle = new Style({
zIndex: 10
});
const cityStyle = new Style({
zIndex: 20
});
Подписи городов будут отображаться поверх дорог.
Стиль может использовать другую геометрию вместо исходной.
new Style({
geometry: function(feature) {
return feature.getGeometry().getInteriorPoint();
}
});
Такой подход часто применяется для подписей полигонов.
Например:
new Style({
geometry: feature =>
feature.getGeometry().getInteriorPoint(),
text: new Text({
text: feature.get('name')
})
});
Текст будет отображён внутри полигона независимо от его формы.
Класс RegularShape позволяет создавать маркеры без
изображений.
import RegularShape from 'ol/style/RegularShape.js';
const triangleStyle = new Style({
image: new RegularShape({
points: 3,
radius: 10,
fill: new Fill({
color: 'red'
})
})
});
Треугольник строится программно и не требует графических файлов.
new Style({
image: new RegularShape({
points: 5,
radius: 15,
radius2: 7,
angle: 0,
fill: new Fill({
color: 'gold'
})
})
});
Параметр radius2 формирует внутренние вершины
звезды.
Создание нового объекта Style для каждого объекта может
снижать производительность.
Неэффективный вариант:
layer.setStyle(function(feature) {
return new Style({
fill: new Fill({
color: 'blue'
})
});
});
Лучше создавать стиль один раз:
const cachedStyle = new Style({
fill: new Fill({
color: 'blue'
})
});
layer.setStyle(function() {
return cachedStyle;
});
Преимущества:
Особенно полезно при тематическом картографировании.
const styleCache = {};
layer.setStyle(function(feature) {
const type = feature.get('type');
if (!styleCache[type]) {
styleCache[type] = new Style({
fill: new Fill({
color: getColor(type)
})
});
}
return styleCache[type];
});
Для каждого значения атрибута создаётся только один экземпляр стиля.
OpenLayers предоставляет методы доступа к настройкам.
const fill = style.getFill();
const stroke = style.getStroke();
const image = style.getImage();
const text = style.getText();
Пример:
const width =
style.getStroke().getWidth();
Стиль можно модифицировать после создания.
style.getStroke().setColor('red');
style.getStroke().setWidth(5);
Изменение текста:
style.getText().setText('Новое название');
Изменение радиуса:
style.getImage().setRadius(15);
После обновления может потребоваться повторная перерисовка слоя.
layer.changed();
const cityStyle = new Style({
image: new CircleStyle({
radius: 8,
fill: new Fill({
color: '#1976d2'
}),
stroke: new Stroke({
color: '#ffffff',
width: 2
})
}),
text: new Text({
font: '14px Arial',
offsetY: -15,
fill: new Fill({
color: '#000'
}),
stroke: new Stroke({
color: '#fff',
width: 3
})
}),
zIndex: 100
});
Использование:
layer.setStyle(function(feature) {
cityStyle
.getText()
.setText(feature.get('name'));
return cityStyle;
});
В результате каждый город отображается:
zIndex.