Skip to content

Use Case #10: Эхолокация рельефа (Связь карты и графика высот)

1. В чем проблема? (Зачем это вообще нужно)

Представь: ты построил на сайте маршрут на 50 километров.

  • Сверху экрана — карта. По ней идет синяя линия твоего пути.
  • Снизу экрана — график высот (горы и ямы). В самой середине графика ты видишь ОГРОМНУЮ ГОРУ.
  • Боль юзера: Ты сидишь и думаешь: "Блин, а где эта гора физически находится на карте? Это в лесу? Возле какого города начнется этот подъем?". Тебе приходится гадать, потому что карта и график — это просто две отдельные неживые картинки.

2. Как это ДОЛЖНО работать (Магия для пользователя)

Мы свяжем карту и график невидимой нитью, чтобы они откликались на движения мышки.

  • Сценарий А: «Ищу гору» Ты просто наводишь курсор мыши на самую высокую гору на графике внизу. В ЭТУ ЖЕ СЕКУНДУ сверху на карте, прямо на твоем синем маршруте, загорается яркий маркер. Ты ведешь мышку по графику вправо-влево (вниз по склону) — а маркер послушно бегает по карте вдоль дороги! Проблема решена за 1 секунду.
  • Сценарий Б: «Смотрю на дорогу» Ты видишь какую-то извилистую тропинку на карте и думаешь: "Тут спуск или подъем?". Наводишь мышку на эту тропинку прямо на карте. В эту же секунду на графике внизу загорается вертикальная полоска-подсветка! Ты сразу видишь ответ.

3. СЕКРЕТ ДЛЯ ПРОГРАММИСТА (Как сделать так, чтобы не глючило)

⚠️ Внимание: тут ошибаются 90% новичков!

Как делать НЕ НАДО (Ошибка координат): Плохой программист попытается связать карту и график по GPS-координатам [x, y]. Почему это сломается: Если юзер поехал маршрут "Туда-Обратно", синяя линия маршрута легла сама на себя. Если юзер наведет мышку на эту дорогу на карте, программа запутается: "Ой! Юзер ехал тут ТУДА (утром) и ОБРАТНО (вечером). Какую высоту мне показать?!". Точка начнет бешено прыгать туда-сюда (Проблема Маятника).

Как делать ПРАВИЛЬНО (Правило «Нитка с бусами»): Забудь про GPS-координаты для этой фичи!

  • Представь, что маршрут — это просто длинная нитка, на которую по очереди надели 5000 бусинок. У каждой бусинки есть строгий порядковый номер (от 0 до 5000). Это называется Индекс.
  • График внизу состоит из тех же самых 5000 бусинок.

Как работает идеальная программа:

  1. Юзер навел мышку на гору на графике. Программа смотрит: "Так, мышка сейчас висит над бусинкой №400".
  2. График ничего не высчитывает, он просто кричит Карте через глобальный стейт: "Эй, Карта! Подсвети красным цветом бусинку №400!".
  3. Карта находит у себя 400-ю бусинку и рисует на ней красную точку. ВСЁ!

Программе абсолютно плевать, что путь "Туда" (бусинка №100) и путь "Обратно" (бусинка №4900) физически лежат на одном асфальте. Номера-то разные! Точка бегает идеально плавно.


4. Высший пилотаж UX (Zoom-to-Selection)

  • Если юзер зажал левую кнопку мыши на графике и выделил прямоугольником всю гору целиком (Drag Selection).
  • Камера на карте автоматически делает Zoom-to-fit (подбирает Bounding Box), крупно и плавно показывая именно этот выделенный подъем на экране.

Эпики и Задачи

Epic 1: Двухсторонняя синхронизация (Нитка с бусами)

  • Task 1.1: Реализовать глобальный стейт hoveredPointIndex (Zustand), принимающий number | null.
  • Task 1.2 (График -> Карта): При mousemove над компонентом Графика вычислять индекс пересечения (по X оси) и сетить его в hoveredPointIndex. Подписывать слой карты на этот индекс для рендера плавающего маркера.
  • Task 1.3 (Карта -> График): При mousemove над MapLibre линией вычислять индекс ближайшей вершины (feature.id или поиск по массиву) и сетить в hoveredPointIndex. Подписывать График на этот индекс для отрисовки вертикального тултипа.

Epic 2: Zoom-to-Selection

  • Task 2.1: Имплементировать выделение (Brush tool) на графике высот.
  • Task 2.2: При событии onBrushEnd извлекать срез массива от startIndex до endIndex, вычислять для него BoundingBox и вызывать метод map.fitBounds(bbox) с плавной анимацией.