Отображение пробок на карте

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

Информация о трафике используется в следующих сценариях:

  • навигационные системы;
  • логистические платформы;
  • службы такси и доставки;
  • диспетчерские панели;
  • системы мониторинга транспорта;
  • аналитические геоинформационные решения.

Данные о дорожной обстановке обновляются на стороне сервисов HERE и отображаются поверх базовой карты в виде специального слоя.


Подключение необходимых модулей

Для работы с картой и дорожной информацией подключаются основные библиотеки платформы HERE:

<script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>

После подключения создаётся объект платформы:

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,
    {
        zoom: 12,
        center: {
            lat: 55.7558,
            lng: 37.6176
        }
    }
);

Добавление интерактивности:

const beh * avior = new H.mapevents.Behavior(
    new H.mapevents.MapEvents(map)
);

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

Что представляет собой слой трафика

В HERE дорожная информация реализуется как отдельный картографический слой.

Он накладывается поверх основной карты и отображает:

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

Каждый тип состояния дороги обозначается собственным цветом.

Типичная цветовая схема:

Цвет Состояние
Зелёный Свободное движение
Жёлтый Замедление
Оранжевый Плотный поток
Красный Пробка
Тёмно-красный Сильный затор

Получение слоя дорожной информации

Объект слоя доступен через набор стандартных слоёв платформы.

const trafficLayer = defaultLayers.vector.normal.traffic;

После получения его необходимо добавить на карту.

map.addLayer(trafficLayer);

Полный пример:

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: 55.7558,
            lng: 37.6176
        },
        zoom: 12
    }
);

const trafficLayer = defaultLayers.vector.normal.traffic;

map.addLayer(trafficLayer);

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


Включение и отключение отображения пробок

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

Добавление слоя:

map.addLayer(trafficLayer);

Удаление слоя:

map.removeLayer(trafficLayer);

Пример переключателя:

let trafficVisible = false;

button.addEventListener('click', () => {

    if (trafficVisible) {
        map.removeLayer(trafficLayer);
    } else {
        map.addLayer(trafficLayer);
    }

    trafficVisible = !trafficVisible;
});

Создание пользовательского переключателя

HTML:

<button id="toggleTraffic">
    Пробки
</button>

Jav * aScript:

const toggleButton =
    document.getElementById('toggleTraffic');

let enabled = false;

toggleButton.addEventListener('click', () => {

    if (enabled) {
        map.removeLayer(trafficLayer);
        toggleButton.textContent = 'Показать пробки';
    } else {
        map.addLayer(trafficLayer);
        toggleButton.textContent = 'Скрыть пробки';
    }

    enabled = !enabled;
});

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


Автоматическое включение слоя при определённом масштабе

На небольших масштабах трафик может создавать визуальный шум.

Для повышения читаемости карты слой включают только после достаточного приближения.

map.addEventListener('mapviewchangeend', () => {

    const zoom = map.getZoom();

    if (zoom >= 10) {
        map.addLayer(trafficLayer);
    } else {
        map.removeLayer(trafficLayer);
    }

});

Проверка наличия слоя

Перед повторным добавлением желательно проверять состояние карты.

Пример:

function hasTrafficLayer() {

    return map.getLayers().asArray()
        .includes(trafficLayer);

}

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

if (!hasTrafficLayer()) {
    map.addLayer(trafficLayer);
}

Это предотвращает появление дублирующихся операций.


Управление несколькими слоями

В реальных проектах одновременно могут использоваться:

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

Пример переключения между типами карты:

function switchToSatellite() {

    map.setBaseLayer(
        defaultLayers.raster.satellite.map
    );

}

При этом слой трафика может оставаться активным:

map.addLayer(trafficLayer);

Благодаря этому пробки отображаются даже поверх спутниковых снимков.


Работа с ночной темой

Во многих интерфейсах используется тёмное оформление.

Создание карты:

const map = new H.Map(
    container,
    defaultLayers.vector.normal.map,
    {
        center: center,
        zoom: 12,
        pixelRatio: window.devicePixelRatio || 1
    }
);

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

Особенно хорошо контрастируют:

  • красные линии заторов;
  • жёлтые предупреждения;
  • зелёные участки свободного движения.

Отображение пробок вместе с маршрутом

Один из наиболее распространённых сценариев — отображение маршрута на фоне актуальной дорожной ситуации.

Создание маршрута:

const routingService =
    platform.getRoutingService(null, 8);

После получения геометрии маршрут добавляется на карту.

const routeLine = new H.map.Polyline(
    lineString,
    {
        style: {
            lineWidth: 6
        }
    }
);

map.addObject(routeLine);

Слой трафика остаётся поверх дорожной сети:

map.addLayer(trafficLayer);

В результате можно визуально оценить:

  • участки заторов;
  • проблемные перекрёстки;
  • скорость движения по маршруту;
  • альтернативные направления объезда.

Использование дорожной информации в диспетчерских системах

В логистике слой пробок часто работает совместно с объектами транспорта.

Пример отображения автомобилей:

vehicles.forEach(vehicle => {

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

    map.addObject(marker);

});

После добавления слоя трафика диспетчер получает возможность анализировать:

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

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

Хотя слой трафика формируется сервером HERE, существуют рекомендации по оптимизации приложения.

Не создавать слой повторно

Неправильно:

button.oncl ick = () => {

    const layer =
        defaultLayers.vector.normal.traffic;

    map.addLayer(layer);

};

Правильно:

const trafficLayer =
    defaultLayers.vector.normal.traffic;

button.oncl ick = () => {
    map.addLayer(trafficLayer);
};

Ограничивать количество перерисовок

Неправильно:

setInterval(() => {
    map.addLayer(trafficLayer);
}, 1000);

Правильно:

if (!hasTrafficLayer()) {
    map.addLayer(trafficLayer);
}

Использовать векторные карты

Современные версии HERE ориентированы на работу с векторными слоями.

defaultLayers.vector.normal.map

Векторная карта обеспечивает:

  • более плавное масштабирование;
  • меньший объём передаваемых данных;
  • высокую скорость отрисовки;
  • лучшую совместимость с дорожными слоями.

Типовая архитектура модуля отображения пробок

Часто управление дорожной информацией выносится в отдельный класс.

class TrafficManager {

    constructor(map, layer) {
        this.map = map;
        this.layer = layer;
        this.enabled = false;
    }

    show() {

        if (!this.enabled) {
            this.map.addLayer(this.layer);
            this.enabled = true;
        }

    }

    hide() {

        if (this.enabled) {
            this.map.removeLayer(this.layer);
            this.enabled = false;
        }

    }

    toggle() {

        if (this.enabled) {
            this.hide();
        } else {
            this.show();
        }

    }

}

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

const trafficManager =
    new TrafficManager(
        map,
        trafficLayer
    );

trafficManager.show();

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