Жесты и мультитач

Жесты в веб-картографии опираются на унифицированную модель взаимодействия указателя, где мышь, сенсорный экран и трекпад приводятся к единому потоку событий. В контексте HERE Technologies управление картой реализуется через слой поведения (behavior layer), который абстрагирует низкоуровневые pointer events и предоставляет готовые механизмы масштабирования, перемещения и вращения сцены.

В основе интерактивности HERE Maps API for JavaScript лежит связка объектов карты и обработчиков событий. Поведение карты не является встроенным состоянием объекта карты — оно подключается отдельно через модуль взаимодействия.

Ключевая архитектурная идея заключается в разделении:

  • рендеринга карты;
  • источника данных (тайлы, векторные слои);
  • слоя взаимодействия (gestures & behaviors).

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


Базовый слой жестов: H.mapevents

Основной механизм обработки жестов реализован через модуль H.mapevents. Он преобразует низкоуровневые DOM-события в семантические действия карты.

Инициализация обычно строится вокруг двух сущностей:

  • H.mapevents.MapEvents — интерпретатор событий;
  • H.mapevents.Behavior — набор стандартных жестов.
const map = new H.Map(
  document.getElementById('map'),
  defaultLayers.vector.normal.map,
  {
    center: { lat: 52.52, lng: 13.405 },
    zoom: 10,
    pixelRatio: window.devicePixelRatio
  }
);

const mapEvents = new H.mapevents.MapEvents(map);

const beh * avior = new H.mapevents.Behavior(mapEvents);

Behavior автоматически активирует стандартный набор жестов:

  • drag для перемещения карты;
  • scroll для масштабирования;
  • pinch для мультитач-зумирования;
  • double tap для быстрого увеличения масштаба;
  • inertia после завершения жеста.

Панорамирование (pan) и инерция движения

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

Особенность системы заключается в наличии инерции. После завершения drag-операции карта продолжает движение, постепенно снижая скорость.

Инерция рассчитывается на основе:

  • скорости последнего перемещения;
  • времени между событиями pointermove;
  • коэффициента затухания, встроенного в behavior.

При необходимости инерция может быть отключена:

behavior.disable(H.mapevents.Behavior.Feature.INERTIA);

Масштабирование: wheel, pinch и double tap

Масштабирование реализуется тремя независимыми сценариями:

Колесо мыши (wheel zoom)

События wheel преобразуются в изменение уровня zoom с дискретной или плавной интерполяцией.

Особенность реализации — центр масштабирования совпадает с позицией курсора, а не с центром экрана.

Pinch gesture

Pinch-жест основан на вычислении расстояния между двумя pointer-объектами:

  • увеличение расстояния → zoom in;
  • уменьшение расстояния → zoom out.

Фактически используется геометрическая модель:

  • начальная дистанция фиксируется при touchstart;
  • последующие изменения переводятся в коэффициент масштабирования.

Double tap zoom

Двойное касание интерпретируется как быстрый zoom-in с фиксированным шагом. В отличие от wheel и pinch, этот жест дискретен и не имеет промежуточных состояний.


Поворот карты (rotation)

Ротация активируется мультитач-жестом с двумя пальцами, где угол между точками контакта изменяется во времени.

Математически используется вычисление угла между векторами:

  • v₁ — начальное положение точек касания;
  • v₂ — текущее положение.

Разница углов применяется к текущему bearing карты.

behavior.enable(H.mapevents.Behavior.Feature.ROTATE);

При отключенной ротации второй палец интерпретируется только как zoom, без изменения ориентации карты.


Tilt и 3D-наклон

В некоторых режимах доступен наклон карты (tilt), создающий псевдотрёхмерную перспективу.

Жест обычно реализуется через комбинацию:

  • right-click drag (desktop);
  • two-finger vertical drag (mobile).

Диапазон наклона ограничен параметрами движка рендеринга WebGL.


Система включения и отключения жестов

Каждый тип взаимодействия в behavior представлен как независимая feature:

  • DRAGGING
  • PINCHING
  • SCROLLING
  • TAP
  • DOUBLE_TAP
  • INERTIA
  • ROTATE

Пример управления:

behavior.disable(H.mapevents.Behavior.Feature.PINCHING);
behavior.disable(H.mapevents.Behavior.Feature.ROTATE);

Такая модель позволяет формировать специализированные сценарии:

  • статические карты без перемещения;
  • киоски с ограниченной интерактивностью;
  • аналитические панели с фиксированным масштабом.

Низкоуровневые pointer events и их трансформация

Все жесты строятся поверх Pointer Events API. Внутри системы происходит нормализация:

  • mouse events;
  • touch events;
  • pen/stylus input.

Далее события агрегируются в единый поток указателей, где каждому pointerId соответствует состояние:

  • координаты;
  • скорость;
  • давление (при наличии);
  • временные метки.

Это позволяет корректно обрабатывать мультисенсорные сценарии без разделения логики по устройствам ввода.


Обработка конфликтов жестов

Одновременные действия (например, pinch + rotate) разрешаются через приоритеты:

  1. multi-touch gestures (pinch/rotate)
  2. single-touch drag
  3. wheel zoom
  4. click/double click

При конфликте behavior вычисляет наиболее вероятную интерпретацию на основе:

  • количества активных pointers;
  • геометрии движения;
  • временных окон активации жеста.

Настройка чувствительности жестов

Параметры взаимодействия могут быть адаптированы через конфигурацию карты и beh * avior:

  • коэффициент скорости pan;
  • чувствительность zoom;
  • порог распознавания double tap;
  • задержка инерции.

Пример изменения чувствительности:

map.getViewModel().setLookAtData({
  zoom: 12,
  tilt: 45,
  heading: 180
});

Хотя данный метод не управляет жестами напрямую, он влияет на визуальный отклик, формируя ощущение инерции и динамики.


Особенности мобильных устройств

На мобильных устройствах жесты интерпретируются с учётом системных особенностей:

  • Safari и Chrome могут добавлять собственные gesture layers;
  • требуется блокировка default touch behavior;
  • учитывается scale viewport.

Часто применяется:

#map {
  touch-action: none;
}

Это отключает системные жесты браузера и передаёт управление HERE behavior.


Интеграция кастомных жестов

Поверх стандартного слоя возможно добавление собственных взаимодействий через подписку на события:

map.addEventListener('tap', (evt) => {
  const coord = map.screenToGeo(
    evt.currentPointer.viewportX,
    evt.currentPointer.viewportY
  );
});

Таким образом строятся:

  • выделение объектов;
  • кастомные контекстные меню;
  • интерактивные слои аналитики.

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

Жесты напрямую влияют на частоту перерисовки карты. Ключевые оптимизации:

  • батчинг pointermove событий;
  • использование requestAnimationFrame;
  • снижение частоты пересчёта матрицы проекции;
  • кеширование tile-слоя при pinch zoom.

При высокой нагрузке behavior может временно снижать детализацию перерисовки, сохраняя плавность взаимодействия.


Архитектурная роль жестов в рендеринге карты

Жесты не являются отдельным модулем интерфейса — они влияют на камеру сцены. Любое действие пользователя преобразуется в изменения:

  • center (географические координаты);
  • zoom level;
  • bearing;
  • tilt.

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