Адаптивные окна

Адаптивные окна в веб-картах на базе HERE Technologies представляют собой механизм отображения всплывающих интерфейсных элементов, которые автоматически подстраиваются под размеры экрана, плотность интерфейса и состояние карты. В JavaScript API такие окна чаще всего реализуются через компоненты UI-слоя и привязываются к географическим координатам или объектам карты, сохраняя корректное позиционирование при масштабировании, панорамировании и изменении ориентации устройства.

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

  • слой карты (rendering layer), отвечающий за отрисовку тайлов и геометрии;
  • слой объектов (map objects), включающий маркеры, полигоны и линии;
  • UI-слой, в котором размещаются интерактивные элементы, включая всплывающие окна.

В JavaScript API используется объектная модель, где окно привязывается к географической точке и синхронизируется с текущим состоянием viewport. При изменении масштаба или центра карты происходит пересчёт координат в экранные пиксели, после чего UI-элемент перерисовывается.

Базовые типы всплывающих окон

В экосистеме HERE Maps JS API применяются несколько типов окон, различающихся уровнем контроля и адаптивности:

H.ui.InfoBubble

Наиболее распространённый компонент, предназначенный для привязки к маркерам и точкам интереса. Обеспечивает автоматическое позиционирование относительно anchor-точки.

H.ui.DomIcon

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

H.overlay

Низкоуровневый механизм для наложения DOM-элементов поверх карты без привязки к UI-логике библиотеки.

Принцип адаптивности

Адаптивность всплывающих окон в HERE Maps API формируется за счёт нескольких механизмов:

  • пересчёт координат при событиях mapviewchange и mapviewchangeend;
  • реакция на события браузера resize и orientationchange;
  • динамическое изменение размеров контейнера карты;
  • автоматическое смещение окна при выходе за границы viewport.

Ключевой принцип заключается в постоянной синхронизации географической точки с пиксельной системой координат.

Привязка окна к объектам карты

Окно чаще всего связывается с маркером следующим образом:

const marker = new H.map.Marker({ lat: 52.5, lng: 13.4 });

const bubble = new H.ui.InfoBubble(marker.getGeometry(), {
  content: 'Точка интереса'
});

ui.addBubble(bubble);
map.addObject(marker);

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

Поведение при изменении масштаба

При масштабировании карты окно может:

  • изменять своё относительное положение для сохранения видимости;
  • смещаться внутрь viewport при приближении к краям;
  • скрываться при выходе объекта за пределы видимой области.

Внутренний алгоритм использует проверку границ viewport и вычисляет оптимальное смещение по осям X и Y.

Обработка событий карты

Для обеспечения корректной адаптации используются следующие события:

  • mapviewchange — непрерывное изменение состояния карты;
  • mapviewchangeend — завершение анимации или трансформации;
  • pointerdown, pointerup — взаимодействие с UI-элементами;
  • resize — изменение размеров контейнера.

Типичная логика обновления положения кастомного окна строится на подписке на mapviewchangeend, чтобы избежать избыточных перерасчётов:

map.addEventListener('mapviewchangeend', () => {
  ui.refresh();
});

Адаптация к мобильным устройствам

На мобильных устройствах поведение всплывающих окон усложняется из-за следующих факторов:

  • динамическая высота viewport (адресная строка браузера);
  • изменение ориентации экрана;
  • высокая плотность пикселей (devicePixelRatio);
  • ограниченное пространство для UI-элементов.

Для корректной работы применяется:

  • пересчёт размеров контейнера при orientationchange;
  • использование относительных единиц измерения в CSS;
  • ограничение максимальной ширины окна;
  • автоматическое центрирование при недостатке места.

Управление DOM-контентом

Если используется кастомный HTML-контент, адаптивность реализуется через CSS и JavaScript одновременно. Важно учитывать, что контейнер окна создаётся динамически и может быть пересоздан при обновлении состояния карты.

Пример структуры:

const html = `
  <div class="popup">
    <div class="popup-title">Объект</div>
    <div class="popup-body">Описание точки</div>
  </div>
`;

const domIcon = new H.map.DomIcon(html);

const marker = new H.map.Marker({ lat: 52.5, lng: 13.4 }, {
  icon: domIcon
});

CSS-правила для адаптивности:

.popup {
  max-width: 240px;
  min-width: 120px;
  word-wrap: break-word;
}

.popup-title {
  font-size: 14px;
  font-weight: 600;
}

.popup-body {
  font-size: 12px;
}

Смещение и авто-позиционирование

Одним из ключевых аспектов является предотвращение выхода окна за пределы экрана. Для этого применяется система смещений (offsets), учитывающая:

  • размер окна;
  • положение маркера;
  • границы viewport;
  • текущий zoom level.

Алгоритм выбирает оптимальную позицию отображения: сверху, снизу, слева или справа от точки привязки.

Конфликты перекрытия элементов

При наличии нескольких окон или плотного расположения маркеров возникает проблема наложения. Для её решения используется:

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

Кластеризация особенно важна при больших наборах данных, где число маркеров превышает несколько тысяч.

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

При интенсивных изменениях состояния карты (анимации, потоковые данные) адаптивные окна могут стать узким местом производительности. Оптимизация достигается за счёт:

  • батчинга обновлений UI;
  • дебаунса событий mapviewchange;
  • минимизации DOM-операций;
  • повторного использования экземпляров окон.

Особенно критично избегать создания новых bubble-объектов при каждом обновлении координат.

Интеграция с пользовательскими контролами

Адаптивные окна часто взаимодействуют с другими UI-компонентами:

  • панели фильтрации;
  • боковые меню;
  • всплывающие карточки объектов;
  • элементы навигации.

При перекрытии интерфейсов применяется z-index управление и динамическое перераспределение слоёв. Важно учитывать, что карта и UI-слой работают независимо, но синхронизируются через общий viewport.

Особенности жизненного цикла окна

Жизненный цикл всплывающего окна включает несколько стадий:

  • создание и привязка к геометрии;
  • добавление в UI-сцену;
  • отображение на карте;
  • обновление позиции при изменениях viewport;
  • удаление при закрытии или смене состояния.

При удалении важно освобождать ссылки, чтобы избежать утечек памяти, особенно в долгоживущих SPA-приложениях.

Динамическое обновление содержимого

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

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

Обновление выполняется через изменение DOM-узла или переустановку содержимого bubble, без изменения его геометрической привязки.

Работа в условиях ограниченного пространства

На малых экранах поведение окон становится более агрессивно адаптивным:

  • окно может разворачиваться на всю ширину экрана;
  • возможен переход в нижний drawer-режим;
  • увеличиваются зоны клика;
  • упрощается визуальная структура.

Такая модель обеспечивает читаемость при минимальном пространстве отображения.

Синхронизация с анимацией карты

При плавных анимациях (pan, zoom) окна следуют за объектами в реальном времени. Для этого используется интерполяция координат и синхронизация с frame update циклами рендеринга.

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