Маршруты в OpenLayers реализуются через векторную геометрию, где основным примитивом выступает LineString — последовательность координат, формирующая линию на карте. Такая модель позволяет описывать как простые пути между двумя точками, так и сложные маршруты с множеством сегментов, поворотов и промежуточных узлов.
Векторный маршрут обычно помещается в слой VectorLayer,
который использует источник данных VectorSource. Геометрия
маршрута может быть создана вручную, загружена из GeoJSON, получена из
внешнего API маршрутизации или импортирована из файлов форматов
GPX/KML.
Базовая структура маршрута строится на основе объекта
LineString, принимающего массив координат:
import LineString from 'ol/geom/LineString.js';
const routeGeometry = new LineString([
[37.6173, 55.7558],
[37.629, 55.75],
[37.640, 55.745]
]);
Однако координаты в OpenLayers должны соответствовать проекции карты.
В большинстве случаев используется EPSG:3857, поэтому
географические координаты необходимо преобразовать:
import {fromLonLat} from 'ol/proj.js';
const routeGeometry = new LineString([
fromLonLat([37.6173, 55.7558]),
fromLonLat([37.629, 55.75]),
fromLonLat([37.640, 55.745])
]);
Для отображения линии используется комбинация
VectorSource и VectorLayer.
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';
import Feature from 'ol/Feature.js';
const routeFeature = new Feature({
geometry: routeGeometry
});
const routeSource = new VectorSource({
features: [routeFeature]
});
const routeLayer = new VectorLayer({
source: routeSource
});
Добавление слоя в карту:
map.addLayer(routeLayer);
Визуальное оформление маршрута определяется через стиль
Style и Stroke. Основные параметры включают
цвет, толщину линии и тип штриховки.
import Style from 'ol/style/Style.js';
import Stroke from 'ol/style/Stroke.js';
const routeStyle = new Style({
stroke: new Stroke({
color: '#1e88e5',
width: 4
})
});
routeLayer.setStyle(routeStyle);
Для отображения альтернативных маршрутов используется штриховая линия:
const alternativeStyle = new Style({
stroke: new Stroke({
color: '#90caf9',
width: 3,
lineDash: [10, 10]
})
});
Такая визуализация часто применяется при сравнении нескольких маршрутов между одинаковыми точками.
Наиболее распространённый способ получения маршрута — формат GeoJSON.
OpenLayers предоставляет готовый формат GeoJSON для
автоматического преобразования данных.
import GeoJSON from 'ol/format/GeoJSON.js';
import VectorSource from 'ol/source/Vector.js';
const geojsonSource = new VectorSource({
url: '/api/route.geojson',
format: new GeoJSON()
});
GeoJSON-структура маршрута:
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[37.6173, 55.7558],
[37.629, 55.75],
[37.640, 55.745]
]
}
}
При использовании GeoJSON важно учитывать систему координат. Часто
данные приходят в EPSG:4326, что требует трансформации:
const geojsonFormat = new GeoJSON({
featureProjection: 'EPSG:3857'
});
Маршруты могут формироваться динамически через внешние сервисы, например OSRM.
Запрос:
https://router.project-osrm.org/route/v1/driving/37.6173,55.7558;37.640,55.745?geometries=geojson
Обработка ответа:
fetch(url)
.then(response => response.json())
.then(data => {
const coordinates = data.routes[0].geometry.coordinates;
const route = new Feature({
geometry: new LineString(
coordinates.map(coord => fromLonLat(coord))
)
});
routeSource.addFeature(route);
});
В таких сценариях важным элементом становится преобразование координат из формата API в проекцию карты.
При изменении точек маршрута геометрия может обновляться без пересоздания слоя:
routeGeometry.setCoordinates([
fromLonLat([37.6173, 55.7558]),
fromLonLat([37.6500, 55.7600])
]);
OpenLayers автоматически перерисует слой при изменении геометрии, так
как наблюдает за состоянием объекта Feature.
Маршруты могут реагировать на события карты. Например, изменение стиля при наведении:
map.on('pointermove', function (event) {
map.forEachFeatureAtPixel(event.pixel, function (feature) {
feature.setStyle(new Style({
stroke: new Stroke({
color: '#ff5252',
width: 5
})
}));
});
});
Для возврата исходного стиля обычно хранится отдельная ссылка на стиль по умолчанию.
Для отображения нескольких маршрутов используется один слой с
несколькими Feature:
const routes = new VectorSource({
features: [
new Feature({ geometry: route1 }),
new Feature({ geometry: route2 }),
new Feature({ geometry: route3 })
]
});
Каждый маршрут может иметь собственный стиль через функцию:
routeLayer.setStyle(function (feature) {
const type = feature.get('type');
if (type === 'fastest') {
return fastStyle;
}
return alternativeStyle;
});
OpenLayers поддерживает специализированные форматы через
ol/format.
GPX:
import GPX from 'ol/format/GPX.js';
const source = new VectorSource({
url: '/data/track.gpx',
format: new GPX()
});
KML:
import KML from 'ol/format/KML.js';
const source = new VectorSource({
url: '/data/route.kml',
format: new KML()
});
Такие форматы часто содержат не только линии маршрута, но и точки интереса и временные данные.
При работе с большим количеством координат линия может выглядеть «ломаной». Для улучшения визуального восприятия применяется упрощение геометрии:
import {simplifyLineString} from 'ol/geom/flat/simplify.js';
Также используется уменьшение количества точек на этапе подготовки данных на сервере.
После добавления маршрута часто выполняется автоматическое центрирование:
map.getView().fit(routeSource.getExtent(), {
padding: [50, 50, 50, 50],
duration: 1000
});
Это позволяет корректно отобразить весь маршрут в пределах текущего viewport.
Для отображения направления движения вдоль линии применяются символы
(Icon или Circle) с привязкой к сегментам
LineString:
import Point from 'ol/geom/Point.js';
const arrow = new Feature({
geometry: new Point(routeGeometry.getCoordinateAt(0.5))
});
Для более сложных случаев используется вычисление угла наклона сегмента и динамическое размещение маркеров вдоль линии.
При отображении множества маршрутов критично учитывать:
Векторный рендер OpenLayers оптимизирован, но перегрузка количеством
Feature приводит к деградации FPS, особенно при сложных
стилях и анимации.
Перемещение объекта вдоль маршрута реализуется через интерполяцию координат:
const coords = routeGeometry.getCoordinates();
let index = 0;
function animate() {
if (index < coords.length) {
markerFeature.getGeometry().setCoordinates(coords[index]);
index++;
requestAnimationFrame(animate);
}
}
Для плавного движения между точками применяется линейная интерполяция между сегментами линии, а не дискретный переход.