Directions API

Directions API в контексте веб-карт представляет собой слой маршрутизации, отвечающий за построение оптимального пути между точками, возврат геометрии маршрута, инструкций для навигации и метаданных о времени и расстоянии. В связке с MapLibre GL JS Directions API не является встроенным компонентом, а подключается через внешние сервисы маршрутизации, такие как OSRM, GraphHopper или коммерческие API, совместимые с форматом GeoJSON и маршрутов.


Типичная схема работы строится вокруг трёх уровней:

1. Клиентский слой (MapLibre GL JS) Отвечает за отображение карты, источников данных (sources) и слоёв (layers). Здесь визуализируется маршрут, точки старта и финиша, а также промежуточные остановки.

2. Сервис маршрутизации (Directions API) Принимает координаты точек и возвращает маршрут в виде:

  • геометрии (polyline или GeoJSON LineString)
  • набора шагов (maneuvers)
  • метаданных (дистанция, длительность)

3. Геопространственный сервер Например:

  • OSRM — высокопроизводительный routing engine на OpenStreetMap данных
  • GraphHopper — гибкий движок маршрутизации с поддержкой профилей
  • коммерческие API (Mapbox Directions, HERE, TomTom)

Формирование запроса к Directions API

Запрос обычно включает:

  • координаты точек маршрута (longitude, latitude)
  • профиль маршрутизации (driving, walking, cycling)
  • параметры оптимизации (alternatives, avoid tolls, geometry precision)

Пример REST-запроса:

GET /route/v1/driving/13.388860,52.517037;13.397634,52.529407?overview=full&geometries=geojson

Ответ возвращается в формате JSON:

{
  "routes": [
    {
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [13.38886, 52.517037],
          [13.392, 52.521],
          [13.397634, 52.529407]
        ]
      },
      "distance": 2300.5,
      "duration": 420,
      "legs": [
        {
          "steps": [
            {
              "name": "Main Street",
              "distance": 500,
              "maneuver": {
                "type": "turn",
                "instruction": "Turn right"
              }
            }
          ]
        }
      ]
    }
  ]
}

Подключение маршрута к MapLibre GL JS

Визуализация маршрута в MapLibre GL JS строится через добавление GeoJSON-источника и слоя линии.

Создание источника данных

map.addSource('route', {
  type: 'geojson',
  data: {
    type: 'Feature',
    geometry: {
      type: 'LineString',
      coordinates: []
    }
  }
});

Добавление слоя отображения маршрута

map.addLayer({
  id: 'route-line',
  type: 'line',
  source: 'route',
  layout: {
    'line-join': 'round',
    'line-cap': 'round'
  },
  paint: {
    'line-color': '#3b82f6',
    'line-width': 5
  }
});

Обновление маршрута после получения ответа Directions API

После получения ответа от сервиса маршрутизации необходимо обновить GeoJSON источник:

fetch(url)
  .then(res => res.json())
  .then(data => {
    const route = data.routes[0];

    map.getSource('route').setData({
      type: 'Feature',
      geometry: route.geometry
    });
  });

В этой модели MapLibre выступает исключительно как рендерер, а вся логика маршрутизации находится вне клиента.


Работа с несколькими точками маршрута

Directions API поддерживает waypoints, что позволяет строить сложные маршруты.

Пример структуры:

A → B → C → D

Запрос:

/route/v1/driving/A;B;C;D

На клиентской стороне важно:

  • поддерживать массив координат
  • синхронизировать порядок точек
  • обновлять маршрут при изменении любой точки

Обработка альтернативных маршрутов

Некоторые API возвращают несколько вариантов маршрута:

"routes": [
  { "distance": 2300 },
  { "distance": 2500 },
  { "distance": 2700 }
]

В MapLibre GL JS это обычно реализуется через несколько GeoJSON источников:

map.addSource('route-alt-1', {...});
map.addSource('route-alt-2', {...});

И отображение с разной стилизацией:

  • основной маршрут — насыщенный цвет
  • альтернативные — прозрачные линии

Декодирование полилинии

Некоторые Directions API возвращают геометрию в виде encoded polyline вместо GeoJSON. В этом случае требуется декодирование.

Алгоритм:

  • получение строки polyline
  • преобразование в массив координат
  • формирование LineString

Пример:

const coordinates = decodePolyline(encoded);

map.getSource('route').setData({
  type: 'Feature',
  geometry: {
    type: 'LineString',
    coordinates
  }
});

Отображение навигационных инструкций

Directions API часто возвращает массив steps:

  • тип манёвра (turn, merge, roundabout)
  • текст инструкции
  • расстояние до следующего шага

Пример структуры:

{
  "steps": [
    {
      "instruction": "Turn left onto Second Street",
      "distance": 300,
      "maneuver": {
        "type": "turn",
        "modifier": "left"
      }
    }
  ]
}

Интеграция с MapLibre GL JS обычно включает:

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

Динамическое обновление маршрута

В интерактивных приложениях маршрут пересчитывается при:

  • перетаскивании маркера
  • изменении точки назначения
  • добавлении нового waypoint

Оптимизация включает:

  • debounce запросов
  • кеширование предыдущих маршрутов
  • отмену незавершённых fetch-запросов через AbortController
const controller = new AbortController();

fetch(url, { signal: controller.signal })
  .then(res => res.json())
  .then(updateRoute);

controller.abort();

Профили маршрутизации

Directions API обычно поддерживает профили:

  • driving — автомобильные дороги
  • walking — пешеходные маршруты
  • cycling — велоинфраструктура

Каждый профиль использует разные правила графа:

  • ограничения скорости
  • доступность дорог
  • типы разрешённых путей

В MapLibre GL JS профиль влияет только на визуализацию, но не на расчёт маршрута.


Работа с таймингом и дистанцией

Метаданные маршрута используются для UI-слоёв:

  • общая длина маршрута
  • предполагаемое время
  • время между шагами

Пример:

const route = data.routes[0];

const distanceKm = route.distance / 1000;
const durationMin = route.duration / 60;

Эти значения часто отображаются как overlay поверх карты.


Кастомизация отображения маршрута

MapLibre GL JS позволяет гибко стилизовать линию маршрута:

  • градиентные линии
  • dashed маршруты
  • динамическая толщина
  • выделение активного участка

Пример динамического изменения:

map.setPaintProperty('route-line', 'line-color', [
  'interpolate',
  ['linear'],
  ['zoom'],
  10, '#60a5fa',
  15, '#1d4ed8'
]);

Разделение маршрута на сегменты

Для продвинутых сценариев маршрут разбивается на:

  • пройденную часть
  • активный сегмент
  • оставшийся путь

Это требует:

  • хранения текущей позиции пользователя
  • вычисления ближайшей точки на линии
  • пересчёта индексов координат

Ошибки и обработка исключений

Типичные проблемы Directions API:

  • отсутствие маршрута между точками
  • неверный формат координат
  • превышение лимита запросов
  • разрыв дорожного графа

Обработка:

if (!data.routes || data.routes.length === 0) {
  console.error('Route not found');
}

Производительность при большом количестве маршрутов

При работе с большим количеством маршрутов важно:

  • использовать simplify геометрии
  • ограничивать количество альтернатив
  • отключать ненужные слои MapLibre
  • использовать worker для обработки данных

Интеграция с real-time трекингом

Directions API часто комбинируется с GPS-потоком:

  • пользователь движется по маршруту
  • позиция обновляется каждые N секунд
  • при отклонении выполняется reroute

Алгоритм:

  1. получение текущей позиции
  2. вычисление отклонения от линии маршрута
  3. вызов нового Directions API запроса при необходимости

Использование кастомных routing backend

Вместо публичных API часто разворачиваются собственные серверы:

  • OSRM server
  • GraphHopper instance
  • Valhalla routing engine

Это позволяет:

  • контролировать данные дорог
  • снижать задержки
  • добавлять кастомные ограничения (например, зоны доступа)

Связь Directions API и слоя визуализации MapLibre

Ключевая особенность интеграции заключается в разделении ответственности:

  • Directions API отвечает за графовую оптимизацию
  • MapLibre GL JS отвечает за визуальное представление

Это разделение позволяет:

  • менять routing backend без изменения UI
  • кастомизировать визуализацию без изменения логики маршрута
  • строить сложные навигационные системы поверх единого интерфейса карты