Клавиатурная навигация в веб-картах является критически важной частью доступности и интерактивности интерфейса. В экосистеме HERE Technologies она реализуется на уровне карты и её UI-компонентов, позволяя пользователю перемещать карту, изменять масштаб и взаимодействовать с объектами без использования мыши.
Основная цель клавиатурного управления — обеспечить полноценную работу карты для пользователей с ограниченной моторикой, а также для сценариев, где мышь недоступна или нежелательна (например, киоски, терминалы, навигационные панели).
Любая интерактивная карта в JavaScript API строится вокруг DOM-элемента контейнера. Именно он становится точкой входа для клавиатурных событий.
Ключевые принципы:
tabindex)focus/blurПростейшая инициализация контейнера:
<div id="mapContainer" tabindex="0"></div>
const platform = new H.service.Platform({
apikey: 'YOUR_API_KEY'
});
const defaultLayers = platform.createDefaultLayers();
const map = new H.Map(
document.getElementById('mapContainer'),
defaultLayers.vector.normal.map,
{
center: { lat: 52.5200, lng: 13.4050 },
zoom: 10,
pixelRatio: window.devicePixelRatio || 1
}
);
Добавление tabindex="0" критично: без него элемент не
может быть активирован с клавиатуры.
В HERE Maps API клавиатурное управление не всегда включено автоматически в зависимости от конфигурации слоя взаимодействия. Основной механизм реализуется через поведенческий объект (behavior).
const beh * avior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
Этот слой отвечает за:
Без подключения MapEvents карта будет реагировать только
на мышь и сенсорные события.
Стандартный набор клавиатурных действий в HERE Maps API включает следующие элементы управления:
Перемещение происходит с фиксированным шагом, зависящим от текущего масштаба.
+ или = — увеличение масштаба- — уменьшение масштабаМасштабирование выполняется относительно центра текущего вида карты.
В зависимости от конфигурации поведения могут поддерживаться:
Page Up / Page Down — альтернативное
масштабированиеHome — возврат к заданному центру (если реализовано в
приложении)Space — временная фиксация взаимодействия (в некоторых
кастомных сценариях)Хотя встроенный behavior покрывает базовые сценарии, в сложных интерфейсах требуется перехват и расширение логики.
Пример обработки событий:
map.getElement().addEventListener('keydown', function (event) {
switch (event.key) {
case 'ArrowUp':
map.getViewModel().setLookAtData({
position: map.getCenter().toScreenCoordinates(map.getZoom())
});
break;
case 'ArrowDown':
map.setCenter({
lat: map.getCenter().lat - 0.01,
lng: map.getCenter().lng
});
break;
}
});
В реальных приложениях прямое изменение координат используется редко;
предпочтительнее применять методы map.getViewModel() и
map.getViewPort() для корректной синхронизации с
внутренними состояниями.
Ключевой аспект клавиатурной навигации — управление фокусом.
Рекомендуемая модель:
tabindexПример контроля состояния:
const mapElement = map.getElement();
mapElement.addEventListener('focus', () => {
behavior.enable();
});
mapElement.addEventListener('blur', () => {
behavior.disable();
});
Такой подход предотвращает конфликт клавиш с другими элементами интерфейса страницы.
При интеграции карты в сложные интерфейсы часто возникают конфликты:
Для устранения конфликтов применяется:
mapElement.addEventListener('keydown', (event) => {
if (document.activeElement !== mapElement) return;
});
event.stopPropagation();
event.preventDefault();
Использовать осторожно, чтобы не нарушить доступность.
В стандартной конфигурации поведение клавиатуры можно модифицировать
через отключение отдельных компонентов mapevents.
Пример отключения жестов при сохранении клавиатуры:
const mapEvents = new H.mapevents.MapEvents(map);
const beh * avior = new H.mapevents.Behavior(mapEvents);
behavior.disable(H.mapevents.Behavior.WHEELZOOM);
Хотя пример показывает отключение колесика мыши, аналогичный принцип применяется для комплексной настройки поведения.
При создании пользовательских контролов важно соблюдать совместимость с клавиатурой.
Пример кастомной кнопки:
const button = document.createElement('button');
button.innerText = 'Zoom +';
button.setAttribute('aria-label', 'Увеличить масштаб карты');
button.addEventListener('click', () => {
map.setZoom(map.getZoom() + 1);
});
button.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
map.setZoom(map.getZoom() + 1);
}
});
Ключевые моменты:
<button> вместо
<div>aria-labelEnter и SpaceДоступность карты напрямую связана с ARIA-разметкой.
Рекомендуемые атрибуты:
<div id="mapContainer"
tabindex="0"
role="application"
aria-label="Интерактивная карта">
</div>
role="application" сообщает скринридерам, что внутри
контейнера работает отдельное интерактивное приложение.
HERE Maps API активно использует слои для отображения данных (тайлы, маркеры, полигоны). При клавиатурной навигации важно учитывать:
Пример защиты от потери событий:
map.addEventListener('mapviewchange', () => {
map.getElement().focus();
});
Более сложный уровень взаимодействия — переход между объектами:
Подход строится на логике «фокусируемого списка объектов»:
const objects = [];
map.addObject(marker);
objects.push(marker);
Навигация:
let index = 0;
map.getElement().addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
e.preventDefault();
index = (index + 1) % objects.length;
map.setCenter(objects[index].getGeometry());
}
});
В продакшене такой механизм дополняется визуальным выделением активного объекта.
При использовании React, Vue или Angular важно учитывать жизненный цикл карты:
MapEvents при remountПример логики:
useEffect(() => {
const map = new H.Map(...);
const mapEvents = new H.mapevents.MapEvents(map);
const beh * avior = new H.mapevents.Behavior(mapEvents);
return () => map.dispose();
}, []);
Хотя клавиатурные события относительно лёгкие, проблемы могут возникать при:
Рекомендуемые подходы:
В некоторых интерфейсах клавиатурная навигация дополняется:
Ctrl + L)Ctrl + F с кастомной логикой)Такие сценарии требуют строгого контроля конфликтов и документирования hotkeys, чтобы не нарушать стандартное поведение браузера.
При переключении между вкладками или элементами интерфейса карта может терять активное состояние.
Типичный подход:
window.addEventListener('blur', () => {
behavior.disable();
});
window.addEventListener('focus', () => {
behavior.enable();
});
Это предотвращает случайные перемещения карты при возврате пользователя на страницу.
Клавиатурная навигация должна оставаться предсказуемой:
Любые кастомные изменения поведения должны сохранять семантику базовых клавиш, иначе теряется совместимость с ожиданиями пользователя и вспомогательными технологиями.