Панель с текстовыми инструкциями

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

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


Структура данных маршрута и источник инструкций

Инструкции формируются объектом результата запроса маршрута, возвращаемого сервисом построения маршрутов. Каждый маршрут содержит:

  • набор альтернативных маршрутов (routes)
  • сегменты пути (legs)
  • шаги (steps)

Каждый шаг представляет отдельное действие навигации:

  • начало и конец манёвра
  • текстовое описание (html_instructions)
  • расстояние (distance)
  • длительность (duration)
  • геометрия сегмента (polyline)

Текстовые инструкции обычно содержат HTML-разметку, включая выделение улиц и ключевых точек маршрута.


Подключение панели через DirectionsRenderer

Встроенный механизм отображения инструкций реализуется через объект DirectionsRenderer. Он связывает маршрут с картой и DOM-элементом панели.

Ключевой метод конфигурации:

  • setPanel(element) — назначает HTML-контейнер для вывода текстовых инструкций

Типовая структура инициализации:

const directionsService = new google.maps.DirectionsService();
const directionsRenderer = new google.maps.DirectionsRenderer();

const map = new google.maps.Map(document.getElementById("map"), {
  zoom: 7,
  center: { lat: 41.85, lng: -87.65 }
});

directionsRenderer.setMap(map);
directionsRenderer.setPanel(document.getElementById("instructions"));

HTML-контейнер становится целевой областью, куда API автоматически рендерит список шагов маршрута.


Создание собственной панели инструкций

Вместо встроенного рендера возможно создание полностью кастомной панели, основанной на обработке объекта DirectionsResult.

Базовая структура DOM:

<div id="map"></div>
<div id="instructions"></div>

Контейнер инструкций может быть оформлен как отдельный UI-блок, закреплённый поверх карты или размещённый сбоку интерфейса.


Ручной разбор маршрута и генерация инструкций

При отказе от DirectionsRenderer данные маршрута обрабатываются вручную:

directionsService.route({
  origin: "Berlin",
  destination: "Munich",
  travelMode: google.maps.TravelMode.DRIVING
}, (result, status) => {
  if (status === "OK") {
    renderSteps(result.routes[0].legs[0].steps);
  }
});

Функция формирования панели:

function renderSteps(steps) {
  const panel = document.getElementById("instructions");
  panel.innerHTML = "";

  steps.forEach(step => {
    const div = document.createElement("div");
    div.className = "step";
    div.innerHTML = `
      <div class="instruction">${step.instructions}</div>
      <div class="meta">
        ${step.distance.text} · ${step.duration.text}
      </div>
    `;
    panel.appendChild(div);
  });
}

Форматирование HTML-инструкций

Поле html_instructions содержит HTML-разметку, которая может включать:

  • названия улиц
  • жирное выделение ключевых объектов
  • ссылки на дорожные элементы
  • указания поворотов

При выводе важно учитывать потенциальные HTML-теги, так как они влияют на отображение.

Для безопасного рендеринга и контроля внешнего вида часто применяется:

  • фильтрация HTML
  • замена тегов на собственные компоненты
  • пост-обработка текста

Стилизация панели инструкций

Визуальная структура панели должна обеспечивать читаемость последовательности шагов.

Пример базовой стилизации:

#instructions {
  width: 320px;
  max-height: 100%;
  overflow-y: auto;
  font-family: Arial, sans-serif;
  background: #fff;
  padding: 12px;
  border-left: 1px solid #ddd;
}

.step {
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #eee;
}

.instruction {
  font-size: 14px;
  line-height: 1.4;
}

.meta {
  font-size: 12px;
  color: #666;
}

Интеграция панели в интерфейс карты

Панель инструкций часто размещается рядом с картой или поверх неё. При использовании Google Maps API можно управлять расположением через систему контролов.

Добавление кастомного элемента:

map.controls[google.maps.ControlPosition.LEFT_TOP].push(
  document.getElementById("instructions")
);

Позиции контролов включают:

  • TOP_LEFT
  • TOP_RIGHT
  • LEFT_TOP
  • RIGHT_BOTTOM
  • BOTTOM_CENTER

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


Обновление панели при изменении маршрута

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

directionsService.route(request, (result, status) => {
  if (status === "OK") {
    directionsRenderer.setDirections(result);
    renderSteps(result.routes[0].legs[0].steps);
  }
});

При использовании DirectionsRenderer обновление происходит автоматически, однако при кастомной реализации требуется явная перерисовка DOM.


Обработка многоэтапных маршрутов

Маршрут может содержать несколько legs, если присутствуют промежуточные точки.

Структура обработки:

result.routes[0].legs.forEach(leg => {
  leg.steps.forEach(step => {
    // обработка каждого шага
  });
});

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

  • точка отправления
  • промежуточные остановки
  • конечная точка

Синхронизация с маркерами и поли линиями

Панель инструкций часто связывается с визуальным маршрутом:

  • подсветка текущего шага
  • выделение соответствующего сегмента polyline
  • синхронное перемещение карты

Пример логики выделения:

function highlightStep(index) {
  document.querySelectorAll(".step").forEach((el, i) => {
    el.classList.toggle("active", i === index);
  });
}

Работа с событиями маршрута

Google Maps API позволяет отслеживать изменения отображения маршрута через события DirectionsRenderer:

  • directions_changed — обновление маршрута
  • map_changed — смена карты

Пример:

directionsRenderer.addListener("directions_changed", () => {
  const directions = directionsRenderer.getDirections();
  const steps = directions.routes[0].legs[0].steps;
  renderSteps(steps);
});

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

При сложных маршрутах количество шагов может достигать сотен элементов. В таких случаях важно учитывать:

  • ленивую отрисовку DOM-элементов
  • виртуализацию списка
  • минимизацию перерисовок

Оптимизация через фрагменты:

const fragment = document.createDocumentFragment();

steps.forEach(step => {
  const div = document.createElement("div");
  div.innerHTML = step.instructions;
  fragment.appendChild(div);
});

panel.appendChild(fragment);

Локализация текстовых инструкций

Инструкции формируются в зависимости от параметров запроса, включая язык интерфейса. Параметр language влияет на:

  • язык описания манёвров
  • формат расстояний
  • локальные названия улиц

Корректная настройка языка повышает читаемость панели и согласованность с интерфейсом приложения.


Расширение панели дополнительными данными

Помимо стандартных шагов, панель может включать:

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

Такие элементы интегрируются в DOM поверх стандартных инструкций и обновляются синхронно с маршрутом.