Контент информационных окон

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

Основная роль информационных окон заключается в связывании визуального слоя карты с динамическими данными: описаниями объектов, результатами поиска, пользовательскими метками, атрибутами POI и произвольной HTML-разметкой.


В JavaScript API HERE Maps чаще всего используется класс:

  • H.ui.InfoBubble — высокоуровневое UI-окно
  • H.map.InfoBubble — низкоуровневый объект карты (в некоторых конфигурациях)

Информационное окно строится вокруг трёх ключевых компонентов:

  • географическая привязка (координаты или объект карты)
  • контент (HTML, текст или DOM-структура)
  • опции отображения (смещение, стиль, поведение закрытия)

Пример логики инициализации:

const bubble = new H.ui.InfoBubble(
  { lat: 52.5, lng: 13.4 },
  {
    content: '<div>Информация об объекте</div>'
  }
);

ui.addBubble(bubble);

Контент задаётся как строка HTML, что обеспечивает гибкость отображения, но требует контроля за безопасностью и производительностью.


Типы контента информационных окон

HTML-контент

Наиболее распространённый формат — HTML-строка. Он позволяет формировать сложные интерфейсы внутри окна:

  • заголовки
  • списки характеристик
  • изображения
  • ссылки
  • кнопки действий
content: `
  <div class="info-window">
    <h3>Объект на карте</h3>
    <p>Описание объекта с дополнительными данными.</p>
  </div>
`

Ключевая особенность заключается в том, что API не ограничивает структуру HTML, поэтому разработчик полностью контролирует визуальное представление.


Динамически формируемый контент

Контент часто генерируется на основе данных маркера:

marker.addEventListener('tap', (evt) => {
  const data = evt.target.getData();

  const bubble = new H.ui.InfoBubble(evt.target.getGeometry(), {
    content: `
      <div>
        <strong>${data.title}</strong>
        <div>${data.description}</div>
      </div>
    `
  });

  ui.addBubble(bubble);
});

Такой подход используется при интеграции с API геокодинга, маршрутизации и внешними REST-сервисами.


DOM-элементы и кастомизация

Вместо строки можно использовать DOM-ноды, что полезно при сложных интерфейсах:

  • формы
  • интерактивные кнопки
  • асинхронные данные
  • графические элементы
const container = document.createElement('div');
container.innerHTML = '<button>Действие</button>';

const bubble = new H.ui.InfoBubble(position, {
  content: container
});

Это позволяет интегрировать информационные окна с приложением без ограничения HTML-строкой.


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

Информационные окна чаще всего связываются с маркерами (H.map.Marker) или объектами (H.map.Object).

Привязка к маркеру

marker.addEventListener('tap', function (evt) {
  const coord = evt.target.getGeometry();

  const bubble = new H.ui.InfoBubble(coord, {
    content: 'Маркер выбран'
  });

  ui.addBubble(bubble);
});

Важный момент: окно привязывается к координате, а не к DOM-элементу маркера.


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

Информационные окна часто требуют корректировки позиции относительно маркера:

  • вертикальное смещение вверх
  • горизонтальная коррекция при краях карты
  • адаптация под масштаб
const bubble = new H.ui.InfoBubble(coord, {
  content: 'Текст',
  offset: new H.math.Point(0, -20)
});

Это предотвращает перекрытие маркера и улучшает читаемость.


Управление жизненным циклом окна

Создание и удаление

Информационные окна не управляются автоматически — их необходимо удалять вручную:

ui.removeBubble(bubble);

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

if (currentBubble) {
  ui.removeBubble(currentBubble);
}
currentBubble = bubble;

Обновление содержимого

Контент может изменяться без пересоздания окна:

bubble.setContent('<div>Новые данные</div>');

Это важно при асинхронной подгрузке информации (fetch/AJAX).


Стилизация информационных окон

Информационные окна имеют встроенные стили, но допускают переопределение через CSS:

  • фон
  • границы
  • тени
  • шрифты
  • размеры

Пример переопределения:

.h-ui-infobubble {
  border-radius: 8px;
  font-family: Arial, sans-serif;
}

Особое внимание уделяется стрелке (tail), которая указывает на объект карты. Её стилизация требует аккуратного изменения псевдоэлементов.


Интерактивность внутри окна

Информационные окна могут содержать полноценные UI-элементы:

  • кнопки действий
  • переключатели
  • ссылки на маршруты
  • формы ввода

Пример обработчика внутри окна:

container.querySelector('button').addEventListener('click', () => {
  console.log('Кнопка нажата');
});

Важно учитывать, что события внутри окна работают в контексте DOM, а не карты.


Работа с несколькими окнами

Одновременное отображение нескольких информационных окон возможно, но требует контроля:

  • управление слоями (z-index)
  • ограничение количества окон
  • группировка по категориям объектов

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

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

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

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

  • частое создание DOM-структур снижает производительность
  • хранение больших HTML-блоков в строках увеличивает нагрузку
  • повторное использование шаблонов ускоряет рендеринг

Оптимизационные подходы:

  • кеширование шаблонов
  • переиспользование одного экземпляра InfoBubble
  • минимизация вложенного DOM

Безопасность контента

Так как контент часто формируется динамически, возникает риск XSS:

  • пользовательские данные должны экранироваться
  • HTML необходимо фильтровать
  • запрещено вставлять неподтверждённые скрипты

Особенно критично при интеграции с внешними API и пользовательским вводом.


Асинхронная загрузка данных

Информационные окна часто используют отложенную загрузку:

const bubble = new H.ui.InfoBubble(coord, {
  content: 'Загрузка...'
});

fetch('/api/object')
  .then(res => res.json())
  .then(data => {
    bubble.setContent(`<div>${data.name}</div>`);
  });

Это позволяет отображать окно мгновенно, а данные подгружать позже.


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

При zoom и pan информационные окна автоматически пересчитывают позицию:

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

Это обеспечивает согласованность отображения с картографическим слоем.


Связь с UI менеджером карты

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

  • добавление bubble
  • удаление bubble
  • управление состоянием интерфейса

В типичной архитектуре:

  • H.Map — карта
  • H.ui.UI — UI-менеджер
  • InfoBubble — элемент отображения

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