Позиционирование InfoBubble

Работа InfoBubble в HERE Maps API for JavaScript тесно связана с системой экранных координат и географической привязкой. Любой всплывающий информационный блок существует одновременно в двух мирах: географическом (широта/долгота) и экранном (пиксели). Позиционирование определяется трансформацией между этими системами и дополнительными параметрами компоновки внутри контейнера карты.

Каждый InfoBubble привязывается к конкретной географической координате. Именно эта точка считается якорной, относительно которой выполняется дальнейший расчёт положения:

const bubble = new H.ui.InfoBubble(
  { lat: 52.5200, lng: 13.4050 },
  {
    content: '<div>Берлин</div>'
  }
);

ui.addBubble(bubble);

Географическая точка не изменяет своего положения при взаимодействии с интерфейсом. Меняется только её проекция на экран, а InfoBubble автоматически пересчитывает позицию при каждом изменении состояния карты (панорамирование, масштабирование, вращение).

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

Внутри системы карта использует проекцию Web Mercator. При каждом обновлении вида выполняется преобразование:

  • географические координаты → мировые координаты
  • мировые координаты → экранные пиксели

InfoBubble опирается на результат второго преобразования. Это означает, что его позиция зависит от текущего viewport и уровня масштабирования.

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

Смещение относительно точки привязки

Для управления визуальным положением используется параметр смещения (offset). Он позволяет сдвигать InfoBubble относительно якорной точки в пикселях:

const bubble = new H.ui.InfoBubble(
  { lat: 52.5200, lng: 13.4050 },
  {
    content: 'Точка интереса',
    offset: new H.math.Point(0, -30)
  }
);

Смещение применяется уже после проекции координаты на экран. Это важный момент: изменение offset не влияет на географическое положение, только на визуальную компоновку.

Основные сценарии применения:

  • предотвращение перекрытия маркера
  • визуальное поднятие пузыря над объектом
  • адаптация под кастомные иконки

Привязка к UI-объектам и маркерам

На практике InfoBubble редко используется изолированно. Чаще всего он связан с объектами H.map.Marker. В этом случае позиция пузыря наследует координаты маркера:

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

const bubble = new H.ui.InfoBubble(marker.getGeometry(), {
  content: 'Маркер'
});

ui.addBubble(bubble);

При изменении позиции маркера InfoBubble автоматически следует за ним, поскольку привязка осуществляется через геометрию объекта.

Автоматическое панорамирование карты

При открытии InfoBubble карта может автоматически смещаться так, чтобы пузырь полностью помещался в видимой области. Этот механизм называется auto-pan.

Он работает следующим образом:

  • вычисляется bounding box пузыря в пикселях
  • сравнивается с размером viewport
  • при выходе за границы карта сдвигается

Поведение можно контролировать через настройки UI-компонента:

const ui = H.ui.UI.createDefault(map, defaultLayers, {
  enableAutoPan: true
});

Включённый auto-pan важен для интерфейсов с плотным размещением маркеров, где всплывающие окна часто выходят за границы экрана.

Перекрытие элементов и приоритет отрисовки

InfoBubble участвует в общей системе слоёв интерфейса. При одновременном отображении нескольких пузырей действует правило z-index:

  • последний открытый элемент получает наивысший приоритет
  • активный InfoBubble всегда отображается поверх маркеров
  • системные UI-элементы могут перекрывать пузырь при высокой приоритетности слоя

При необходимости можно управлять порядком вручную, удаляя и повторно добавляя элементы в UI.

Динамическое обновление позиции

При изменении содержимого InfoBubble (например, загрузка данных по API) его размеры могут меняться. Это приводит к перерасчёту позиционирования, особенно если включён auto-pan.

bubble.setContent('<div style="width:200px">Загрузка...</div>');

Изменение размеров влияет на:

  • вертикальное смещение относительно якоря
  • необходимость повторного центрирования
  • пересчёт границ viewport

Влияние масштабирования карты

При изменении zoom уровень детализации растёт или уменьшается, но географическая точка остаётся фиксированной. Однако визуальное поведение InfoBubble может изменяться:

  • при высоком zoom пузырь занимает меньшую долю экрана
  • при низком zoom возрастает вероятность выхода за границы viewport
  • offset остаётся постоянным в пикселях, что делает его визуально различным на разных масштабах

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

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

Позиция InfoBubble пересчитывается при следующих событиях:

  • pan (перемещение карты)
  • zoom (масштабирование)
  • resize viewport
  • rotation (если поддерживается конфигурацией карты)

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

Контроль границ отображения

Для предотвращения обрезания InfoBubble используются проверки выхода за пределы viewport. Алгоритм учитывает:

  • ширину и высоту пузыря
  • позицию якоря
  • текущий zoom
  • padding интерфейса

Если пузырь выходит за границы, применяется компенсирующее смещение карты либо перерасчёт позиции offset.

Практика стабилизации интерфейса

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

  • фиксированные offset для однотипных маркеров
  • отключение автоцентрирования в плотных кластерах
  • ограничение максимальной ширины InfoBubble
  • синхронизация с состоянием UI слоя карты

Такой подход предотвращает «скачки» интерфейса при массовом обновлении данных.

Поведение при множественных InfoBubble

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

В таких сценариях важно учитывать:

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

Система не выполняет автоматическое разнесение InfoBubble по экрану, поэтому логика распределения часто реализуется на уровне приложения.