При построении маршрута навигационная система должна не только вычислить путь между точками, но и сформировать набор инструкций для движения. В экосистеме Mapbox эта информация предоставляется сервисом маршрутизации через объект маршрута, содержащий последовательность шагов (steps) и манёвров (maneuvers).
Манёвр представляет собой конкретное действие, которое необходимо выполнить в определённой точке маршрута:
Каждый шаг маршрута содержит объект maneuver,
описывающий действие максимально подробно.
Пример структуры ответа:
{
"maneuver": {
"bearing_after": 180,
"bearing_before": 90,
"location": [37.6176, 55.7558],
"modifier": "right",
"type": "turn",
"instruction": "Turn right onto Tverskaya Street"
}
}
Основные свойства:
| Свойство | Описание |
|---|---|
type |
Тип манёвра |
modifier |
Направление действия |
instruction |
Готовая текстовая инструкция |
location |
Координаты точки манёвра |
bearing_before |
Азимут до манёвра |
bearing_after |
Азимут после манёвра |
Для получения детализированных инструкций необходимо запросить
маршрут через Directions API с параметром steps=true.
Пример запроса:
const url =
'https://api.mapbox.com/directions/v5/mapbox/driving/' +
'37.6176,55.7558;37.6200,55.7600' +
'?steps=true' +
'&geometries=geojson' +
'&access_token=' + mapboxgl.accessToken;
fetch(url)
.then(response => response.json())
.then(data => {
console.log(data);
});
После получения данных инструкции находятся внутри структуры:
data.routes[0].legs[0].steps
Каждый элемент массива представляет отдельный этап маршрута.
Пример:
const steps = data.routes[0].legs[0].steps;
steps.forEach(step => {
console.log(step.maneuver.instruction);
});
Результат:
Head north on Tverskaya Street
Turn right onto Mokhovaya Street
Continue straight
Arrive at destination
Типичный шаг содержит большое количество информации.
Пример:
{
distance: 320.5,
duration: 45.1,
name: "Tverskaya Street",
geometry: {...},
maneuver: {...},
mode: "driving",
driving_side: "right"
}
Наиболее важные поля:
Расстояние данного сегмента маршрута.
console.log(step.distance);
Результат:
320.5
Значение указывается в метрах.
Время прохождения сегмента.
console.log(step.duration);
Результат:
45.1
Единица измерения — секунды.
Название дороги.
console.log(step.name);
Пример:
Leninsky Prospekt
Описание действия навигации.
console.log(step.maneuver);
Именно этот объект используется для формирования интерфейса пошаговой навигации.
Поле type определяет категорию действия.
Обычный поворот.
{
type: "turn",
modifier: "left"
}
Инструкция:
Turn left
Начало маршрута.
{
type: "depart"
}
Инструкция:
Head north
Завершение маршрута.
{
type: "arrive"
}
Инструкция:
You have arrived
Перестроение на другую дорогу.
{
type: "merge"
}
Пример:
Merge onto highway
Въезд на автомагистраль.
{
type: "on ramp"
}
Пример:
Take the ramp
Съезд с автомагистрали.
{
type: "off ramp"
}
Пример:
Take exit 5
Круговое движение.
{
type: "roundabout"
}
Пример:
Enter the roundabout
Поворот внутри кольцевой развязки.
{
type: "roundabout turn"
}
Используется в некоторых странах и схемах дорожной сети.
Продолжение движения без изменения направления.
{
type: "continue"
}
Инструкция:
Continue straight
Достижение конца дороги.
{
type: "end of road"
}
Пример:
At the end of the road turn right
Развилка.
{
type: "fork"
}
Пример:
Keep left at the fork
Изменение названия дороги без изменения направления движения.
{
type: "new name"
}
Пример:
Continue onto Garden Ring
Информационное сообщение.
{
type: "notification"
}
Используется для дополнительных уведомлений маршрута.
Поле modifier уточняет направление действия.
modifier: "left"
Поворот налево.
modifier: "right"
Поворот направо.
modifier: "straight"
Движение прямо.
modifier: "slight left"
Небольшое отклонение влево.
modifier: "slight right"
Небольшое отклонение вправо.
modifier: "sharp left"
Резкий поворот налево.
modifier: "sharp right"
Резкий поворот направо.
modifier: "uturn"
Разворот.
Готовые инструкции можно вывести в пользовательском интерфейсе.
HTML:
<div id="instructions"></div>
Jav * aScript:
const instructions =
document.getElementById('instructions');
steps.forEach(step => {
const div = document.createElement('div');
div.textContent =
step.maneuver.instruction;
instructions.appendChild(div);
});
Результат:
Head north
Turn right onto Main Street
Continue straight
Arrive at destination
const list = document.createElement('ol');
steps.forEach(step => {
const item = document.createElement('li');
item.textContent =
step.maneuver.instruction;
list.appendChild(item);
});
document.body.appendChild(list);
Получается классический пошаговый навигатор.
Информация о длине сегмента уже присутствует в объекте шага.
steps.forEach(step => {
console.log(
step.maneuver.instruction,
step.distance
);
});
Вывод:
Turn right 120
Continue straight 450
Turn left 80
Более удобный вариант:
steps.forEach(step => {
console.log(
`${step.maneuver.instruction} (${Math.round(step.distance)} м)`
);
});
function formatDistance(distance) {
if (distance >= 1000) {
return (distance / 1000).toFixed(1) + ' км';
}
return Math.round(distance) + ' м';
}
Использование:
console.log(
formatDistance(step.distance)
);
Пример:
2.3 км
Для повышения удобства интерфейса тип манёвра можно преобразовывать в иконки.
function getIcon(type, modifier) {
if (type === 'turn') {
if (modifier === 'left') {
return '⬅';
}
if (modifier === 'right') {
return '➡';
}
}
if (type === 'arrive') {
return '?';
}
return '↑';
}
Использование:
steps.forEach(step => {
console.log(
getIcon(
step.maneuver.type,
step.maneuver.modifier
),
step.maneuver.instruction
);
});
Каждый манёвр содержит координаты.
step.maneuver.location
Пример:
steps.forEach(step => {
new mapboxgl.Marker()
.setLngLat(step.maneuver.location)
.addTo(map);
});
На карте появятся маркеры в местах выполнения действий.
Инструкцию можно показать во всплывающем окне.
steps.forEach(step => {
const popup = new mapboxgl.Popup({
offset: 20
}).setText(
step.maneuver.instruction
);
new mapboxgl.Marker()
.setLngLat(step.maneuver.location)
.setPopup(popup)
.addTo(map);
});
При движении по маршруту навигатор обычно показывает ближайшее действие.
Пример поиска следующего шага:
function getNextStep(index) {
return steps[index + 1];
}
Вывод инструкции:
const nextStep = getNextStep(currentIndex);
if (nextStep) {
console.log(
nextStep.maneuver.instruction
);
}
Текст манёвров совместим с Web Speech API.
function speak(text) {
const utterance =
new SpeechSynthesisUtterance(text);
speechSynthesis.speak(utterance);
}
Использование:
speak(
step.maneuver.instruction
);
Пример команды:
Turn left onto Main Street
Directions API позволяет получать инструкции на различных языках.
Пример:
const url =
'https://api.mapbox.com/directions/v5/mapbox/driving/' +
coordinates +
'?steps=true' +
'&language=ru' +
'&access_token=' + mapboxgl.accessToken;
Результат:
Поверните направо
Через 300 метров держитесь левее
Вы прибыли в пункт назначения
Поддерживаются десятки языков, включая:
Для автомагистралей Directions API предоставляет дополнительные сведения.
Пример:
step.destinations
Содержимое:
Airport, City Center
Информация может использоваться для отображения дорожных указателей.
Для кругового движения присутствуют специальные свойства.
Пример:
{
type: "roundabout",
exit: 3
}
Поле exit показывает номер съезда.
console.log(
`Съезд №${step.maneuver.exit}`
);
Результат:
Съезд №3
Пример комплексного интерфейса:
function renderInstructions(steps) {
const container =
document.getElementById('instructions');
container.innerHTML = '';
steps.forEach(step => {
const row =
document.createElement('div');
row.className = 'instruction';
row.innerHTML = `
<strong>
${step.maneuver.instruction}
</strong>
<br>
${Math.round(step.distance)} м
`;
container.appendChild(row);
});
}
Подобный подход используется большинством веб-навигаторов и
транспортных приложений. Благодаря объектам step и
maneuver библиотека Mapbox GL JS в сочетании с Directions
API позволяет создавать полноценные навигационные интерфейсы с
текстовыми подсказками, визуализацией манёвров, голосовым
сопровождением, локализацией и отображением ключевых точек маршрута на
карте.