Множественные информационные окна в картографических приложениях на базе HERE Maps API требуют отдельной архитектуры управления, поскольку стандартная модель UI предполагает ограниченное количество одновременно отображаемых всплывающих элементов. При увеличении числа маркеров и интерактивных объектов возникает задача координации состояния окон, предотвращения их наложения и контроля жизненного цикла каждого экземпляра.
В HERE Maps JavaScript API (версии 3.x) для отображения всплывающих
окон используется компонент H.ui.InfoBubble. Он
привязывается к географической точке и отображается поверх карты в
UI-слое.
Создание базового информационного окна:
var bubble = new H.ui.InfoBubble(
{ lat: 52.5200, lng: 13.4050 },
{ content: '<b>Берлин</b><br/>Столица Германии' }
);
ui.addBubble(bubble);
Ключевая особенность: каждый InfoBubble является
самостоятельным объектом UI и не управляет другими окнами автоматически.
Это означает, что при добавлении нескольких окон разработчик обязан
самостоятельно контролировать их поведение.
При добавлении нескольких маркеров с привязанными окнами часто возникает ситуация:
Без централизованного управления интерфейс быстро становится перегруженным.
Практическим решением является создание менеджера, который контролирует все активные окна. Основная идея — хранить ссылку на текущее открытое окно и закрывать его перед открытием нового.
function InfoBubbleManager(ui) {
this.ui = ui;
this.activeBubble = null;
}
InfoBubbleManager.prototype.open = function(position, content) {
if (this.activeBubble) {
this.ui.removeBubble(this.activeBubble);
}
this.activeBubble = new H.ui.InfoBubble(position, {
content: content
});
this.ui.addBubble(this.activeBubble);
};
InfoBubbleManager.prototype.close = function() {
if (this.activeBubble) {
this.ui.removeBubble(this.activeBubble);
this.activeBubble = null;
}
};
Такой подход обеспечивает строгую модель: одно активное окно в интерфейсе, отсутствие конфликтов отображения.
В ряде сценариев требуется отображение нескольких окон одновременно, например:
В этом случае используется коллекция окон вместо единственной ссылки.
function MultiBubbleManager(ui) {
this.ui = ui;
this.bubbles = [];
}
MultiBubbleManager.prototype.open = function(position, content) {
var bubble = new H.ui.InfoBubble(position, {
content: content
});
this.ui.addBubble(bubble);
this.bubbles.push(bubble);
return bubble;
};
MultiBubbleManager.prototype.closeAll = function() {
this.bubbles.forEach(function(b) {
this.ui.removeBubble(b);
});
this.bubbles = [];
};
Частый сценарий — связывание InfoBubble с объектами
H.map.Marker. Важно учитывать, что маркер сам по себе не
хранит состояние окна, поэтому связь реализуется через события.
var marker = new H.map.Marker({ lat: 52.5, lng: 13.4 });
map.addObject(marker);
marker.addEventListener('tap', function(evt) {
var coord = map.screenToGeo(
evt.currentPointer.viewportX,
evt.currentPointer.viewportY
);
infoManager.open(coord, '<b>Точка интереса</b>');
});
В этом подходе координаты события используются для позиционирования окна, что обеспечивает точную привязку к визуальному элементу.
При множественных окнах возникает проблема перекрытия. Одно из решений — смещение окон относительно маркера.
var bubble = new H.ui.InfoBubble(position, {
content: content,
offset: { x: 0, y: -20 }
});
Другой подход — динамическая коррекция позиции на основе масштаба карты:
Для контроля состояния окон применяются события карты и UI:
mapviewchange — изменение области отображения;tap — закрытие окон при клике вне маркера;Пример закрытия всех окон при клике по карте:
map.addEventListener('tap', function(evt) {
if (evt.target instanceof H.map.Marker === false) {
infoManager.close();
}
});
Это предотвращает накопление неактуальных окон.
При работе с API данных (например, подгрузка объектов с сервера) окна часто создаются асинхронно.
fetch('/api/points')
.then(res => res.json())
.then(data => {
data.forEach(function(item) {
var marker = new H.map.Marker(item.coords);
map.addObject(marker);
marker.addEventListener('tap', function() {
infoManager.open(item.coords, item.html);
});
});
});
В этом случае важно учитывать:
При сотнях и тысячах точек использование индивидуальных окон становится неэффективным. Применяются стратегии:
1. Ленивая инициализация окон Окно создаётся только при взаимодействии пользователя.
2. Переиспользование одного экземпляра Один
InfoBubble перемещается между точками вместо создания новых
объектов.
3. Кластеризация маркеров Группировка объектов снижает количество потенциальных окон.
var clusteringProvider = new H.clustering.Provider(dataPoints);
var layer = new H.map.layer.ObjectLayer(clusteringProvider);
map.addLayer(layer);
При одновременном отображении нескольких окон критически важно управление порядком отрисовки. HERE UI позволяет влиять на приоритет отображения через порядок добавления объектов:
Для сложных интерфейсов применяется стратегия пересоздания активного окна при изменении фокуса.
Содержимое окон может включать произвольный HTML, что позволяет строить сложные интерфейсы:
var content =
'<div class="bubble">' +
'<h3>Объект</h3>' +
'<button oncl ick="handleAction()">Действие</button>' +
'</div>';
infoManager.open(position, content);
При этом необходимо учитывать:
Информационные окна должны реагировать на изменение карты:
Пример пересоздания окна при изменении масштаба:
map.addEventListener('mapviewchange', function() {
if (infoManager.activeBubble) {
var pos = infoManager.activeBubble.getPosition();
var content = infoManager.activeBubble.getContent();
infoManager.open(pos, content);
}
});
Такой подход обеспечивает корректное позиционирование при любых трансформациях карты.
При построении сложных картографических интерфейсов используется модульная структура:
Разделение ответственности позволяет: