Динамические стили

Динамические стили в HERE Maps API основаны на разделении данных и визуального представления. Карта строится как набор слоёв (layers), каждый из которых может быть переопределён во время выполнения без пересоздания самой карты. Такой подход позволяет изменять внешний вид карты в ответ на события интерфейса, изменения состояния приложения или внешние данные.

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


Базовые механизмы смены стиля карты

В JavaScript API базовая карта создаётся через объект платформы и контейнер карты:

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

const defaultLayers = platform.createDefaultLayers();

const map = new H.Map(
  document.getElementById('map'),
  defaultLayers.vector.normal.map,
  {
    center: { lat: 52.52, lng: 13.405 },
    zoom: 10,
    pixelRatio: window.devicePixelRatio || 1
  }
);

Смена стиля базового слоя выполняется через замену layer:

map.setBaseLayer(defaultLayers.vector.hybrid.map);

Варианты стандартных слоёв обычно включают:

  • normal.map — стандартный стиль
  • satellite.map — спутниковый
  • hybrid.map — гибридный режим
  • terrain.map — рельефный слой

Динамическая смена слоя происходит без пересоздания объекта карты, что обеспечивает плавность интерфейса.


Использование style JSON и модификация во время выполнения

Векторные стили HERE основаны на декларативных JSON-описаниях. Они могут быть изменены частично или полностью во время работы приложения.

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

const customStyle = new H.map.Style('style.json', 'https://assets.example.com/styles/');

const vectorLayer = platform.getOMVService().createLayer(customStyle);

map.setBaseLayer(vectorLayer);

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

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

Изменение стиля в runtime возможно через подмену style instance:

const nightStyle = new H.map.Style('night-style.json');

vectorLayer.setStyle(nightStyle);

Условная стилизация объектов (feature-based styling)

Одним из ключевых механизмов динамических стилей является стилизация на основе свойств объектов (feature properties).

Пример функции стиля:

const styleFunction = (data) => {
  if (data.get('traffic') === 'heavy') {
    return {
      strokeColor: 'red',
      lineWidth: 6
    };
  }

  return {
    strokeColor: 'green',
    lineWidth: 3
  };
};

Применение к слою:

const vectorLayer = new H.map.layer.ObjectLayer({
  dataProvider: provider,
  style: styleFunction
});

Такой подход позволяет:

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

Масштабозависимые стили

Динамическая стилизация часто привязывается к уровню zoom, что позволяет адаптировать карту под читаемость.

const zoomStyleFunction = (zoom, feature) => {
  if (zoom < 10) {
    return {
      visibility: false
    };
  }

  if (zoom < 14) {
    return {
      lineWidth: 2
    };
  }

  return {
    lineWidth: 5,
    strokeColor: '#3366ff'
  };
};

Использование:

const layer = new H.map.layer.ObjectLayer({
  style: zoomStyleFunction
});

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

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

Стилизация слоёв (layers)

Векторные слои в HERE Maps API поддерживают динамическое обновление стиля без пересоздания данных.

const layer = platform.getOMVService().createLayer(defaultStyle);

map.addLayer(layer);

Изменение визуализации слоя:

layer.getProvider().setStyle(customStyle);

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

function switchTheme(theme) {
  const style = theme === 'dark'
    ? new H.map.Style('dark.json')
    : new H.map.Style('light.json');

  layer.getProvider().setStyle(style);
}

Динамическое обновление маркеров и объектов

Маркерные объекты поддерживают изменение стиля после добавления на карту.

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

map.addObject(marker);

Изменение внешнего вида:

marker.setIcon(new H.map.Icon('icon-red.png'));

Для объектов с геометрией:

polyline.setStyle({
  strokeColor: '#ff0000',
  lineWidth: 4
});

Динамические изменения часто применяются для:

  • выделения выбранных объектов
  • отображения состояния (активен/неактивен)
  • визуализации потоков данных в реальном времени

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

Стили часто изменяются в ответ на пользовательские события.

map.addEventListener('tap', (evt) => {
  const target = evt.target;

  if (target instanceof H.map.Marker) {
    target.setIcon(new H.map.Icon('selected.png'));
  }
});

Изменение стиля при наведении:

map.addEventListener('pointermove', (evt) => {
  const obj = map.getObjectAt(evt.currentPointer.viewportX, evt.currentPointer.viewportY);

  if (obj) {
    obj.setStyle({ strokeColor: '#00ff00' });
  }
});

Типовые события:

  • tap
  • pointermove
  • longpress
  • dragstart / dragend

Динамическая визуализация данных в реальном времени

Динамические стили часто связаны с потоковыми данными:

setInterval(() => {
  trafficLayer.getProvider().setStyle((feature) => {
    const speed = feature.get('speed');

    if (speed < 20) {
      return { strokeColor: 'red' };
    }

    if (speed < 60) {
      return { strokeColor: 'orange' };
    }

    return { strokeColor: 'green' };
  });
}, 5000);

Используется для:

  • транспортных потоков
  • телеметрии
  • IoT-данных
  • мониторинга объектов

Оптимизация динамической стилизации

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

Основные практики:

  • минимизация пересоздания style объектов
  • использование мемоизации функций стиля
  • группировка обновлений через requestAnimationFrame
  • ограничение частоты пересчёта (throttling)
let lastUpdate = 0;

function updateStyle(feature) {
  const now = Date.now();

  if (now - lastUpdate < 100) {
    return;
  }

  lastUpdate = now;

  return {
    strokeColor: feature.get('status') === 'ok' ? 'green' : 'red'
  };
}

Комбинирование тем и пользовательских слоёв

Динамические стили часто строятся как комбинация базовой темы и наложенных слоёв:

const baseLayer = platform.createDefaultLayers().vector.normal.map;
map.setBaseLayer(baseLayer);

const overlay = new H.map.layer.ObjectLayer(customProvider);
map.addLayer(overlay);

Слои могут включать:

  • дорожные события
  • пользовательские POI
  • тепловые карты
  • зоны интереса

Каждый слой может иметь независимую систему стилей, которая обновляется отдельно.


Реактивная стилизация на основе состояния приложения

Стили могут зависеть от глобального состояния интерфейса:

function setMode(mode) {
  const style = new H.map.Style(
    mode === 'analysis' ? 'analysis.json' : 'standard.json'
  );

  vectorLayer.getProvider().setStyle(style);
}

Используемые состояния:

  • аналитический режим
  • навигация
  • просмотр трафика
  • режим редактирования

Такой подход превращает карту в реактивный UI-компонент, где визуализация напрямую зависит от состояния приложения.