Работа с маршрутами в MapLibre GL JS строится вокруг концепции источников данных (sources) и слоёв (layers), где геометрия пути представляется в формате GeoJSON, чаще всего как LineString или MultiLineString. Отображение маршрута включает несколько этапов: получение координат маршрута, преобразование данных в GeoJSON, добавление источника на карту и визуализация слоя линии с необходимыми стилями.
Маршрут в веб-картографии почти всегда приходит из внешнего routing-сервиса. Наиболее распространённый вариант — использование OSRM, GraphHopper или аналогичных сервисов, возвращающих координаты пути.
Типичный ответ содержит массив координат:
{
"routes": [
{
"geometry": {
"coordinates": [
[71.4304, 51.1282],
[71.4321, 51.1295],
[71.4350, 51.1310]
],
"type": "LineString"
}
}
]
}
Данные уже готовы к использованию в MapLibre, поскольку GeoJSON LineString является нативным форматом для отображения линий.
Перед добавлением на карту маршрут преобразуется в полноценный GeoJSON Feature:
function buildRouteFeature(coordinates) {
return {
type: "Feature",
geometry: {
type: "LineString",
coordinates
},
properties: {}
};
}
Такая обёртка позволяет в дальнейшем расширять маршрут дополнительными атрибутами: длиной, временем, типом дороги или состоянием.
MapLibre использует систему источников, где маршрут регистрируется
как geojson source:
map.on("load", () => {
map.addSource("route", {
type: "geojson",
data: {
type: "Feature",
geometry: {
type: "LineString",
coordinates: []
}
}
});
});
Пустой массив координат позволяет инициализировать структуру заранее, а затем динамически обновлять маршрут после получения данных от API.
После добавления источника создаётся слой линии. Именно он отвечает за визуализацию маршрута:
map.addLayer({
id: "route-line",
type: "line",
source: "route",
layout: {
"line-join": "round",
"line-cap": "round"
},
paint: {
"line-color": "#2E86FF",
"line-width": 5,
"line-opacity": 0.9
}
});
Ключевые параметры:
line-join: round — сглаживает углы поворотовline-cap: round — делает окончания линии мягкимиline-color — цвет маршрутаline-width — толщина линииПосле получения данных от сервиса маршрутизации слой обновляется
через setData:
fetch("https://router.project-osrm.org/route/v1/driving/71.4304,51.1282;71.4350,51.1310?overview=full&geometries=geojson")
.then(res => res.json())
.then(data => {
const route = data.routes[0].geometry;
map.getSource("route").setData({
type: "Feature",
geometry: route
});
});
MapLibre моментально перерисовывает слой без необходимости пересоздания источника или слоя.
После построения маршрута часто требуется автоматически подогнать видимую область:
function fitRouteBounds(coordinates) {
const bounds = coordinates.reduce((b, coord) => {
return b.extend(coord);
}, new maplibregl.LngLatBounds(coordinates[0], coordinates[0]));
map.fitBounds(bounds, {
padding: 40
});
}
Такой подход обеспечивает полное отображение маршрута на экране независимо от его длины и географии.
Для сложных сценариев маршрут может быть разделён на части: активный участок, пройденный и оставшийся.
map.addLayer({
id: "route-completed",
type: "line",
source: "route",
paint: {
"line-color": "#00C853",
"line-width": 5
},
filter: ["<=", ["get", "progress"], 0.5]
});
Для этого в properties каждого сегмента добавляются
дополнительные метки прогресса или состояния.
Для визуализации движения объекта по линии используется интерполяция координат:
let step = 0;
function animate() {
const coordinates = routeCoordinates.slice(0, step);
map.getSource("route").setData({
type: "Feature",
geometry: {
type: "LineString",
coordinates
}
});
step++;
if (step < routeCoordinates.length) {
requestAnimationFrame(animate);
}
}
Такой метод создаёт эффект «прорисовки» пути в реальном времени.
Для отображения альтернативных маршрутов или режима навигации используется пунктирная линия:
map.addLayer({
id: "route-dashed",
type: "line",
source: "route",
layout: {
"line-cap": "round"
},
paint: {
"line-color": "#FF6D00",
"line-width": 4,
"line-dasharray": [2, 2]
}
});
Параметр line-dasharray управляет длиной штрихов и
пробелов, создавая визуально отличимые маршруты.
В навигационных системах часто требуется отображать альтернативные пути:
map.addSource("routes", {
type: "geojson",
data: {
type: "FeatureCollection",
features: []
}
});
Каждый маршрут добавляется как отдельный Feature с уникальными стилями:
map.addLayer({
id: "route-primary",
type: "line",
source: "routes",
paint: {
"line-color": "#1E88E5",
"line-width": 5
},
filter: ["==", ["get", "type"], "primary"]
});
map.addLayer({
id: "route-secondary",
type: "line",
source: "routes",
paint: {
"line-color": "#90CAF9",
"line-width": 4
},
filter: ["==", ["get", "type"], "secondary"]
});
MapLibre позволяет привязывать события к маршруту, включая hover и click:
map.on("click", "route-line", (e) => {
const coordinates = e.lngLat;
new maplibregl.Popup()
.setLngLat(coordinates)
.setHTML("Точка маршрута")
.addTo(map);
});
Для более сложной логики можно использовать
queryRenderedFeatures, получая ближайшие точки маршрута под
курсором.
При работе с протяжёнными маршрутами важно учитывать производительность:
line-simplify на стороне сервераmaxzoom для слоя маршрутаПример ограничения зума:
map.addLayer({
id: "route-line",
type: "line",
source: "route",
maxzoom: 18,
paint: {
"line-color": "#3F51B5",
"line-width": 4
}
});
Маршрут редко отображается сам по себе — обычно он сопровождается точками начала и конца:
new maplibregl.Marker({ color: "green" })
.setLngLat(start)
.addTo(map);
new maplibregl.Marker({ color: "red" })
.setLngLat(end)
.addTo(map);
Эти элементы усиливают читаемость маршрута и позволяют быстро интерпретировать направление движения.
В системах трекинга маршрут может изменяться динамически. В таком случае источник данных регулярно пересчитывается:
setInterval(async () => {
const data = await getUpdatedRoute();
map.getSource("route").setData(data);
}, 5000);
Это позволяет синхронизировать карту с движением транспорта или пользователя без перезагрузки слоя.
Маршрут может менять внешний вид в зависимости от свойств:
paint: {
"line-color": [
"case",
["==", ["get", "traffic"], "heavy"],
"#D32F2F",
"#1976D2"
],
"line-width": 5
}
Такой подход позволяет визуализировать дорожную обстановку, тип покрытия или приоритет маршрута без создания дополнительных слоёв.