Стилизация линий

Стилизация линейных объектов в OpenLayers опирается на комбинацию классов Style, Stroke и геометрий типа LineString и MultiLineString. Векторный слой (VectorLayer) отображает линии через canvas или WebGL (в зависимости от конфигурации), применяя стиль к каждой геометрии на этапе рендеринга.

Ключевой элемент управления внешним видом линии — объект ol/style/Stroke, который определяет цвет, толщину, тип штриха и поведение соединений сегментов.

import Style from 'ol/style/Style.js';
import Stroke from 'ol/style/Stroke.js';

const lineStyle = new Style({
  stroke: new Stroke({
    color: '#2a6fdb',
    width: 3
  })
});

Такой стиль задаёт базовую визуализацию: сплошную синюю линию фиксированной толщины.


Stroke: параметры отображения линии

Объект Stroke управляет низкоуровневым поведением отрисовки.

Цвет линии

Цвет задаётся строкой в формате HEX, RGB или RGBA:

new Stroke({
  color: 'rgba(255, 0, 0, 0.8)',
  width: 2
});

Использование альфа-канала позволяет управлять прозрачностью линий, что особенно важно при наложении множества слоёв.


Толщина линии

Параметр width определяет толщину в пикселях:

new Stroke({
  color: '#000',
  width: 10
});

Толщина влияет не только на визуальное восприятие, но и на интерактивность: hit-detection (попадание курсора) также учитывает ширину.


Тип соединений и окончания линий

OpenLayers поддерживает управление геометрией стыков сегментов:

  • lineCap — оформление концов линии
  • lineJoin — оформление соединений сегментов
new Stroke({
  color: '#333',
  width: 6,
  lineCap: 'round',
  lineJoin: 'round'
});

Возможные значения:

  • butt — обрезанный конец
  • round — скругление
  • square — квадратное продолжение

Для соединений:

  • bevel — срезанный угол
  • round — скругление
  • miter — острый угол

miter особенно важен при острых поворотах линии, где может возникать эффект «шипов», контролируемый параметром miterLimit.


Ограничение углов (miterLimit)

new Stroke({
  color: '#000',
  width: 5,
  lineJoin: 'miter',
  miterLimit: 10
});

miterLimit задаёт максимальную длину выступа при острых углах. При превышении значения происходит переход к bevel.


Пунктирные и штриховые линии

Один из наиболее часто используемых эффектов — пунктирные линии, реализуемые через lineDash.

new Stroke({
  color: '#0066ff',
  width: 3,
  lineDash: [10, 5]
});

Массив определяет чередование:

  • 10 пикселей — линия
  • 5 пикселей — пробел

Более сложные паттерны:

lineDash: [1, 3, 5, 3]

Это создаёт повторяющийся ритмический рисунок, полезный для отображения границ, маршрутов или вспомогательных слоёв.


Анимация и динамическая стилизация линий

Стили в OpenLayers могут задаваться функцией, что позволяет изменять внешний вид в зависимости от масштаба, атрибутов или состояния объекта.

const styleFunction = (feature, resolution) => {
  const speed = feature.get('speed');

  return new Style({
    stroke: new Stroke({
      color: speed > 60 ? 'red' : 'green',
      width: 2 + speed / 20
    })
  });
};

Такой подход используется для:

  • визуализации интенсивности движения
  • отображения категорий объектов
  • адаптации стиля к масштабу карты

Масштабозависимая стилизация

Параметр resolution позволяет менять стиль в зависимости от масштаба карты.

const styleFunction = (feature, resolution) => {
  const width = resolution > 10 ? 1 : 4;

  return new Style({
    stroke: new Stroke({
      color: '#1f78b4',
      width: width
    })
  });
};

При увеличении масштаба линии могут становиться толще или тоньше, а также менять цвет или структуру.


Использование градиентов и сложных цветов

Хотя OpenLayers не предоставляет прямого API для CSS-градиентов в линиях, эффект градиента можно имитировать через canvas-стили или сегментацию линии.

Базовый подход — использование RGBA с изменением прозрачности:

new Stroke({
  color: 'rgba(255, 165, 0, 0.4)',
  width: 6
});

Более сложные визуальные эффекты достигаются через кастомный рендеринг renderFeature или WebGL-слой.


Привязка стиля к геометрии LineString

Линии обычно представляются через LineString:

import Feature from 'ol/Feature.js';
import LineString from 'ol/geom/LineString.js';

const line = new Feature({
  geometry: new LineString([
    [0, 0],
    [1000000, 1000000]
  ])
});

Стиль применяется к объекту целиком:

line.setStyle(lineStyle);

Или через слой:

import VectorLayer from 'ol/layer/Vector.js';

const layer = new VectorLayer({
  source: vectorSource,
  style: lineStyle
});

MultiLineString и различия в стилизации

Для сложных объектов используется MultiLineString, содержащий несколько независимых линий.

new LineString([...])
new MultiLineString([
  [[0, 0], [10, 10]],
  [[20, 20], [30, 30]]
]);

Один стиль применяется ко всем подлиниям, но при необходимости можно использовать функцию стиля для дифференциации.


Контекстные стили и атрибуты объектов

OpenLayers позволяет привязывать визуальные свойства к данным feature.

const styleFunction = (feature) => {
  const type = feature.get('type');

  const colors = {
    highway: '#ff0000',
    road: '#000000',
    path: '#00aa00'
  };

  return new Style({
    stroke: new Stroke({
      color: colors[type] || '#666',
      width: 3
    })
  });
};

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


Прозрачность и наложение линий

При работе с множеством слоёв важно учитывать порядок отрисовки и прозрачность:

new Stroke({
  color: 'rgba(0, 0, 255, 0.2)',
  width: 8
});

Комбинация широкой полупрозрачной линии с узкой непрозрачной создаёт эффект «обводки»:

new Style({
  stroke: new Stroke({
    color: '#0033cc',
    width: 6
  })
});

Зависимость внешнего вида от масштаба карты

В OpenLayers масштаб выражается через resolution. Чем выше значение resolution, тем дальше масштаб.

const styleFunction = (feature, resolution) => {
  const baseWidth = 2;
  const width = baseWidth * Math.max(1, 50 / resolution);

  return new Style({
    stroke: new Stroke({
      color: '#1a1a1a',
      width
    })
  });
};

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


Сложные комбинированные стили линий

Часто применяется наложение нескольких стилей через массив:

feature.setStyle([
  new Style({
    stroke: new Stroke({
      color: '#000',
      width: 8
    })
  }),
  new Style({
    stroke: new Stroke({
      color: '#00aaff',
      width: 4
    })
  })
]);

Это создаёт эффект обводки (outline), повышающий читаемость линий на сложных подложках.


Производительность при стилизации большого количества линий

При работе с тысячами объектов критично минимизировать пересоздание стилей. Рекомендуется:

  • переиспользовать экземпляры Style
  • избегать создания новых объектов в каждом вызове функции стиля
  • кэшировать стили по типу или атрибутам
const cache = {};

function getStyle(type) {
  if (!cache[type]) {
    cache[type] = new Style({
      stroke: new Stroke({
        color: type === 'main' ? '#ff0000' : '#999',
        width: 3
      })
    });
  }
  return cache[type];
}

Использование zIndex для управления перекрытием линий

zIndex влияет на порядок отрисовки:

new Style({
  stroke: new Stroke({
    color: '#000',
    width: 4
  }),
  zIndex: 10
});

Линии с большим zIndex отображаются поверх других, что важно при визуализации транспортных сетей и маршрутов.


Влияние canvas-рендеринга на визуальный результат

В Canvas-рендерере OpenLayers линии рисуются с учётом антиалиасинга браузера. Это влияет на:

  • гладкость диагоналей
  • визуальную толщину тонких линий
  • восприятие полупрозрачности

Толщина менее 1 пикселя может интерпретироваться по-разному в зависимости от devicePixelRatio, что важно учитывать при адаптивной стилизации.