Объект Style

Объект 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
    })
});

В результате:

  • внутренняя часть полигона будет полупрозрачной синей;
  • граница станет синей;
  • толщина границы составит 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
        })
    })
);

Если стиль задан объекту, он имеет приоритет над настройками слоя.


Структура объекта Style

Конструктор принимает объект конфигурации:

const style = new Style({
    fill: fillObject,
    stroke: strokeObject,
    image: imageObject,
    text: textObject,
    geometry: geometryObject,
    zIndex: 10
});

Основные параметры:

Параметр Назначение
fill Заливка
stroke Контур
image Символы для точек
text Подписи
geometry Альтернативная геометрия
zIndex Порядок отрисовки

Использование Fill

Класс 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

Класс 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

Определяет форму концов линии.

lineCap: 'butt'
lineCap: 'round'
lineCap: 'square'

lineJoin

Определяет форму соединения сегментов.

lineJoin: 'round'
lineJoin: 'bevel'
lineJoin: 'miter'

lineDash

Создаёт пунктир.

stroke: new Stroke({
    color: 'black',
    width: 2,
    lineDash: [8, 4]
})

Результат:

  • 8 пикселей линия;
  • 4 пикселя промежуток.

Стилизация точек через Circle

Для отображения точек часто используется класс 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

Для отображения пользовательских изображений применяется класс 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

Класс 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

text

Содержимое подписи.

text: 'Река Волга'

font

Настройка шрифта.

font: 'bold 14px Verdana'

textAlign

Горизонтальное выравнивание.

textAlign: 'left'
textAlign: 'center'
textAlign: 'right'

textBaseline

Вертикальное выравнивание.

textBaseline: 'middle'

offsetX и offsetY

Смещение подписи.

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

Параметр zIndex определяет порядок отображения.

new Style({
    zIndex: 100
});

Чем больше значение, тем выше объект находится визуально.

Пример:

const roadStyle = new Style({
    zIndex: 10
});

const cityStyle = new Style({
    zIndex: 20
});

Подписи городов будут отображаться поверх дорог.


Альтернативная геометрия через geometry

Стиль может использовать другую геометрию вместо исходной.

new Style({
    geometry: function(feature) {
        return feature.getGeometry().getInteriorPoint();
    }
});

Такой подход часто применяется для подписей полигонов.

Например:

new Style({
    geometry: feature =>
        feature.getGeometry().getInteriorPoint(),

    text: new Text({
        text: feature.get('name')
    })
});

Текст будет отображён внутри полигона независимо от его формы.


Использование RegularShape

Класс 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.