Keyboard navigation

Клавиатурная навигация в MapLibre GL JS представляет собой встроенный механизм взаимодействия с картой без использования мыши или сенсорного ввода. Она реализуется через набор обработчиков событий клавиатуры, интегрированных в систему управления картой и тесно связанных с состоянием canvas и интерактивными контроллерами.

Поведение клавиатуры по умолчанию ориентировано на доступность и соответствует типовым паттернам веб-картографических интерфейсов: перемещение карты, изменение масштаба и (при включённых соответствующих режимах) управление поворотом.


Включение и отключение клавиатурного управления

В MapLibre GL JS клавиатурная навигация контролируется через опцию и внутренний обработчик событий.

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

const map = new maplibregl.Map({
  container: 'map',
  style: 'https://demotiles.maplibre.org/style.json',
  center: [30.3, 59.9],
  zoom: 10,
  keyboard: true
});

Значение keyboard: true включает обработку клавиш, false полностью отключает её. При отключении карта перестаёт реагировать на стрелки, клавиши масштабирования и другие встроенные комбинации.


Базовые действия клавиатуры

Стандартная модель управления предполагает следующие действия:

Перемещение карты

Клавиши-стрелки изменяют центр карты:

  • ← сдвиг влево
  • → сдвиг вправо
  • ↑ сдвиг вверх
  • ↓ сдвиг вниз

Скорость смещения зависит от текущего масштаба: чем ближе масштаб, тем меньше шаг перемещения.


Масштабирование

Клавиши управления масштабом:

  • + / = — увеличение масштаба
  • - — уменьшение масштаба

Масштабирование выполняется плавно, с анимацией, аналогично жесту колесика мыши или pinch-to-zoom.


Поворот и наклон (при включённых режимах)

Если активированы соответствующие возможности камеры:

  • Shift + стрелки — поворот карты
  • Shift + Page Up / Page Down — изменение угла наклона

Эти действия зависят от конфигурации dragRotate и поддержки pitch/rotation в стиле.


Фокусировка карты и tabindex

Клавиатурная навигация невозможна без корректного фокуса DOM-элемента. В MapLibre GL JS canvas автоматически получает tabindex, что позволяет переводить фокус на карту через клавишу Tab.

Внутренняя структура включает контейнер:

  • map.getContainer() — внешний div
  • map.getCanvas() — canvas-элемент рендеринга WebGL

При потере фокуса клавиатурные события перестают обрабатываться, даже если keyboard: true.


Поведение при взаимодействии с формами и UI

Ключевая особенность обработки клавиатуры заключается в том, что карта должна «уступать» ввод в элементы интерфейса.

Типичное поведение:

  • если фокус находится в <input>, <textarea> или любом editable-элементе — обработка клавиш картой отключается автоматически
  • стрелки и символы передаются элементу формы
  • обработчики карты не перехватывают события

Это предотвращает конфликт между вводом текста и управлением картой.


Внутренний обработчик KeyboardHandler

Внутри MapLibre GL JS клавиатурная логика реализована через KeyboardHandler, который является частью системы handlers.

Он отвечает за:

  • регистрацию событий keydown
  • интерпретацию кодов клавиш
  • преобразование нажатий в вызовы методов камеры (panBy, zoomIn, zoomOut, easeTo)
  • контроль активного состояния (enable/disable)

Обработчик привязывается к карте при создании и может быть отключён через API:

map.keyboard.disable();

или включён обратно:

map.keyboard.enable();

События клавиатуры и расширение поведения

Хотя базовая логика встроена, карта предоставляет доступ к низкоуровневым событиям DOM.

Пример перехвата нажатий:

map.getCanvas().addEventListener('keydown', (e) => {
  if (e.key === 'r') {
    map.resetNorth();
  }
});

В этом случае кастомная логика дополняет стандартную систему, но требует аккуратного управления:

  • предотвращение e.preventDefault() может блокировать встроенные действия
  • перехват событий на canvas не заменяет внутренний KeyboardHandler

Конфликты клавиатуры и их разрешение

Ключевые проблемные сценарии возникают при совмещении карты с интерфейсными компонентами:

Горячие клавиши приложения

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

Решение:

  • отключать keyboard при открытии модальных окон
  • использовать проверку document.activeElement
  • временно выключать обработчик

Ввод текста поверх карты

При наличии панели поиска или фильтров карта должна игнорировать клавиши:

  • проверка фокуса input-элементов
  • управление через keyboard.enable()/disable()

Доступность и ARIA-поведение

Клавиатурная навигация в MapLibre GL JS тесно связана с доступностью интерфейса.

Реализация включает:

  • возможность управления без мыши
  • предсказуемое поведение стрелок
  • поддержка табуляции
  • корректную работу с screen readers через DOM-контейнер

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

  • role="region"
  • aria-label
  • tabindex="0"

Кастомизация поведения клавиш

В некоторых приложениях требуется изменение стандартной схемы управления.

Типовые подходы:

Переопределение логики через обработчик

map.getCanvas().addEventListener('keydown', (e) => {
  if (e.key === 'ArrowUp') {
    e.preventDefault();
    map.panBy([0, -100]);
  }
});

Блокировка отдельных клавиш

Можно фильтровать поведение внутри собственного слоя управления:

  • игнорировать +/-
  • переназначать стрелки
  • отключать вращение через Shift

Полное отключение и замена

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

map.keyboard.disable();

Далее управление реализуется через внешние hotkeys-библиотеки.


Производительность обработки событий

Клавиатурные события генерируются с высокой частотой при удержании клавиши. Внутренняя реализация MapLibre оптимизирует:

  • троттлинг перемещений камеры
  • сглаживание анимаций
  • объединение последовательных pan-операций

Это предотвращает перегрузку render loop WebGL и сохраняет стабильную частоту кадров даже при длительном удержании клавиш.


Особенности поведения на разных устройствах

Несмотря на ориентированность на десктоп:

  • на ноутбуках с macOS стрелки часто взаимодействуют с системными функциями (Mission Control)
  • на Windows возможно перехватывание клавиш сочетаниями ОС
  • в некоторых браузерах требуется явный фокус canvas

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


Связь клавиатуры с камерой

Любое клавиатурное действие транслируется в операции над камерой:

  • pan → изменение center
  • zoom → изменение zoom
  • rotate → изменение bearing
  • pitch → изменение pitch

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