Настройка внешнего вида контролов

HERE Technologies предоставляет набор интерфейсных компонентов, построенных поверх HERE Maps API for JavaScript, где визуальная часть контролов отделена от логики карты. Это позволяет изменять внешний вид элементов управления без вмешательства в базовую функциональность карты.

Контролы в системе делятся на стандартные (zoom, compass, scale bar, attribution) и пользовательские компоненты, подключаемые через UI-фреймворк H.ui.

Основная точка кастомизации сосредоточена в слоях:

  • CSS-темизация UI контейнера
  • конфигурация H.ui.UI
  • переопределение DOM-шаблонов контролов
  • добавление пользовательских контролов через H.ui.Control

Архитектура UI-контролов

UI слой в HERE Maps построен поверх абстракции H.ui.UI, которая создаёт набор DOM-элементов и связывает их с картой:

var platform = new H.service.Platform({
  apikey: 'YOUR_API_KEY'
});

var defaultLayers = platform.createDefaultLayers();

var map = new H.Map(
  document.getElementById('map'),
  defaultLayers.vector.normal.map,
  {
    center: { lat: 52.52, lng: 13.405 },
    zoom: 10
  }
);

var ui = H.ui.UI.createDefault(map, defaultLayers);

Функция createDefault создаёт стандартный набор контролов. Именно этот слой является отправной точкой для стилизации.


Базовая настройка внешнего вида через CSS

Все контролы рендерятся в DOM и имеют предсказуемую структуру классов. Основные контейнеры:

  • .H_ui
  • .H_control
  • .H_zoom_control
  • .H_mapsettings_control
  • .H_scalebar

Изменение внешнего вида часто начинается с переопределения CSS:

.H_ui {
  font-family: Inter, sans-serif;
}

.H_control {
  background: rgba(20, 20, 20, 0.75);
  border-radius: 10px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
}

.H_zoom_control button {
  width: 36px;
  height: 36px;
  color: #ffffff;
  background: transparent;
  border: none;
}

.H_zoom_control button:hover {
  background: rgba(255, 255, 255, 0.1);
}

CSS-подход используется для глобального изменения визуального языка интерфейса, не затрагивая поведение контролов.


Управление набором стандартных контролов

Стандартные элементы можно включать или отключать через опции UI:

var ui = H.ui.UI.createDefault(map, defaultLayers, 'ru-RU', {
  zoom: false,
  scalebar: false,
  panorama: false
});

Это позволяет упростить интерфейс и оставить только необходимые элементы.


Позиционирование контролов

Каждый контрол может быть размещён в одном из углов карты. Система использует layout-сетки:

  • top-left
  • top-right
  • bottom-left
  • bottom-right

Пример перемещения стандартного контроллера масштаба:

ui.removeControl('scalebar');

var customScaleBar = new H.ui.ScaleBar({
  alignment: H.ui.LayoutAlignment.BOTTOM_LEFT
});

ui.addControl('custom-scalebar', customScaleBar);

Позиционирование часто используется при создании интерфейсов с фиксированными панелями поверх карты.


Переопределение визуального поведения контролов

Некоторые контролы допускают конфигурацию стилей через параметры конструктора:

var zoomControl = new H.ui.ZoomControl({
  alignment: H.ui.LayoutAlignment.TOP_RIGHT,
  uiTheme: H.ui.UI_THEME.LIGHT
});

ui.addControl('zoom', zoomControl);

Темизация влияет на:

  • цвета кнопок
  • контрастность иконок
  • фон контейнера
  • hover-состояния

В более сложных сценариях UI-тема полностью синхронизируется с дизайном приложения.


Работа с внутренними DOM-элементами

Каждый контрол создаёт DOM-структуру, доступ к которой возможен через getElement():

var zoomControl = ui.getControl('zoom');

var element = zoomControl.getElement();

element.style.border = '1px solid #2f2f2f';
element.style.backdropFilter = 'blur(6px)';

Этот способ используется при тонкой кастомизации, когда CSS недостаточно.


Создание пользовательских контролов

Для расширения интерфейса используется базовый класс H.ui.Control.

Пример создания собственного контроллера:

var CustomButtonControl = H.ui.Control.extend({
  constructor: function (options) {
    H.ui.Control.call(this);

    var container = document.createElement('div');
    container.className = 'custom-control';

    var button = document.createElement('button');
    button.innerText = 'Сбросить вид';

    container.appendChild(button);
    this.setElement(container);

    button.addEventListener('click', function () {
      options.map.setCenter({ lat: 52.52, lng: 13.405 });
      options.map.setZoom(10);
    });
  }
});

var resetControl = new CustomButtonControl({ map: map });
ui.addControl('reset', resetControl, H.ui.LayoutAlignment.TOP_LEFT);

Пользовательские контролы интегрируются в тот же layout engine, что и стандартные.


Интеграция кастомных иконок и графики

Контролы часто требуют замены стандартных SVG-иконок:

.H_zoom_control .H_btn-increase::before {
  content: '';
  background-image: url('/icons/zoom-in.svg');
  background-size: contain;
}

Или через DOM:

var btn = zoomControl.getElement().querySelector('.H_btn-increase');
btn.innerHTML = '<img src="/icons/zoom-in.svg">';

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


Темизация через глобальные переменные UI

UI слой поддерживает глобальные настройки темы:

H.ui.UI.createDefault(map, defaultLayers, 'ru-RU', {
  theme: {
    backgroundColor: '#1e1e1e',
    controlColor: '#2c2c2c',
    textColor: '#ffffff'
  }
});

В зависимости от версии SDK, поддержка может варьироваться, но концепция остаётся одинаковой: централизованная тема переопределяет стили всех контролов.


Изоляция стилей и предотвращение конфликтов

Контролы работают в общем DOM-дереве страницы, поэтому возможны конфликты с глобальными стилями приложения. Для минимизации влияния применяются техники:

  • использование пространств имён классов H_*
  • повышение специфичности CSS
  • контейнерная изоляция карты
  • использование all: unset в критических местах

Пример изоляции:

#map-container .H_ui * {
  box-sizing: border-box;
}

Динамическое изменение внешнего вида во время работы карты

Стили контролов можно менять в рантайме в зависимости от состояния приложения:

function setDarkMode(enabled) {
  var uiElement = ui.getElement();

  if (enabled) {
    uiElement.classList.add('dark-ui');
  } else {
    uiElement.classList.remove('dark-ui');
  }
}

CSS:

.dark-ui .H_control {
  background: rgba(0, 0, 0, 0.8);
  color: #fff;
}

Такой подход часто используется при переключении светлой и тёмной темы.


Комбинирование нескольких UI-слоёв

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

var panel = document.createElement('div');
panel.className = 'side-panel';

document.getElementById('map').appendChild(panel);

panel.style.position = 'absolute';
panel.style.top = '0';
panel.style.left = '0';
panel.style.width = '300px';
panel.style.height = '100%';

UI контролы HERE Maps при этом остаются отдельным слоем, синхронизированным с картой, но не зависящим от внешнего DOM.


Управление прозрачностью и визуальной иерархией

Контролы можно визуально «поднимать» или «приглушать» через z-index и прозрачность:

.H_control {
  opacity: 0.9;
  z-index: 10;
}

.H_control:hover {
  opacity: 1;
}

Это влияет на читаемость интерфейса при наложении на сложные карты с высокой плотностью данных.


Кастомизация состояний взаимодействия

Контролы поддерживают состояния:

  • hover
  • active
  • disabled

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

.H_control button:active {
  transform: scale(0.95);
}

.H_control button:disabled {
  opacity: 0.4;
  pointer-events: none;
}

Эти состояния критичны для создания предсказуемого интерфейса.


Расширение UI через плагины

В архитектуре UI возможно создание модулей, которые добавляют наборы контролов:

function TrafficPlugin(ui, map) {
  var button = new H.ui.Control();

  var el = document.createElement('div');
  el.innerText = 'Трафик';
  el.className = 'traffic-toggle';

  button.setElement(el);

  el.addEventListener('click', function () {
    var layer = map.getBaseLayer();
    layer.setVisibility(!layer.getVisibility());
  });

  ui.addControl('traffic', button, H.ui.LayoutAlignment.TOP_RIGHT);
}

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