Отображение линий транспорта

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

Для визуализации транспортных маршрутов используется объект H.map.Polyline, который позволяет строить линии любой сложности и применять к ним различные стили оформления.


Создание простой транспортной линии

Транспортная линия формируется из последовательности географических точек. Для хранения координат применяется объект H.geo.LineString.

const lineString = new H.geo.LineString();

lineString.pushPoint({ lat: 50.4501, lng: 30.5234 });
lineString.pushPoint({ lat: 50.4540, lng: 30.5300 });
lineString.pushPoint({ lat: 50.4580, lng: 30.5400 });

const transportLine = new H.map.Polyline(lineString);

map.addObject(transportLine);

В данном примере создаётся ломаная линия, проходящая через три координаты.


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

По умолчанию линия отображается стандартным стилем. Для транспортных объектов обычно требуется индивидуальное оформление.

Изменение цвета

const transportLine = new H.map.Polyline(lineString, {
    style: {
        strokeColor: '#0066ff',
        lineWidth: 6
    }
});

Результат:

  • цвет линии — синий;
  • толщина — 6 пикселей.

Полупрозрачные линии

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

const transportLine = new H.map.Polyline(lineString, {
    style: {
        strokeColor: 'rgba(255, 0, 0, 0.7)',
        lineWidth: 8
    }
});

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


Пунктирные линии

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

const transportLine = new H.map.Polyline(lineString, {
    style: {
        strokeColor: '#444',
        lineWidth: 4,
        lineDash: [10, 5]
    }
});

Значения массива определяют:

  • длину штриха;
  • длину промежутка между штрихами.

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

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

const busRoute = new H.geo.LineString();

busRoute.pushPoint({ lat: 50.4501, lng: 30.5234 });
busRoute.pushPoint({ lat: 50.4515, lng: 30.5280 });
busRoute.pushPoint({ lat: 50.4542, lng: 30.5340 });
busRoute.pushPoint({ lat: 50.4580, lng: 30.5400 });

const busLine = new H.map.Polyline(busRoute, {
    style: {
        strokeColor: '#28a745',
        lineWidth: 7
    }
});

map.addObject(busLine);

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


Отображение линии метро

Для метро обычно используются более толстые и яркие линии.

const metroRoute = new H.geo.LineString();

metroRoute.pushPoint({ lat: 50.4400, lng: 30.5000 });
metroRoute.pushPoint({ lat: 50.4450, lng: 30.5150 });
metroRoute.pushPoint({ lat: 50.4500, lng: 30.5300 });

const metroLine = new H.map.Polyline(metroRoute, {
    style: {
        strokeColor: '#ff0000',
        lineWidth: 10
    }
});

map.addObject(metroLine);

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


Отображение железнодорожных путей

Железнодорожные линии обычно отображаются серыми или чёрными цветами.

const railwayLine = new H.map.Polyline(railwayRoute, {
    style: {
        strokeColor: '#555555',
        lineWidth: 5,
        lineDash: [4, 4]
    }
});

Пунктир помогает визуально отличать железнодорожные пути от автомобильных маршрутов.


Создание линии из массива координат

Часто данные маршрутов поступают от сервера в формате массива объектов.

const routePoints = [
    { lat: 50.4501, lng: 30.5234 },
    { lat: 50.4520, lng: 30.5260 },
    { lat: 50.4550, lng: 30.5320 },
    { lat: 50.4580, lng: 30.5400 }
];

const lineString = new H.geo.LineString();

routePoints.forEach(point => {
    lineString.pushPoint(point);
});

const routeLine = new H.map.Polyline(lineString);

map.addObject(routeLine);

Такой подход удобен при работе с REST API и внешними транспортными сервисами.


Использование данных маршрутизации HERE

Сервис маршрутизации HERE может возвращать геометрию пути между остановками или станциями.

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

const route = result.routes[0];

const lineString = H.geo.LineString.fromFlexiblePolyline(
    route.sections[0].polyline
);

const routeLine = new H.map.Polyline(lineString, {
    style: {
        strokeColor: '#1b468d',
        lineWidth: 6
    }
});

map.addObject(routeLine);

Преимущества такого подхода:

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

Добавление нескольких транспортных линий

На карте нередко отображается целая транспортная сеть.

const routes = [
    {
        color: '#ff0000',
        points: [
            { lat: 50.45, lng: 30.52 },
            { lat: 50.46, lng: 30.53 }
        ]
    },
    {
        color: '#008000',
        points: [
            { lat: 50.44, lng: 30.51 },
            { lat: 50.47, lng: 30.55 }
        ]
    }
];

routes.forEach(route => {

    const lineString = new H.geo.LineString();

    route.points.forEach(point => {
        lineString.pushPoint(point);
    });

    const polyline = new H.map.Polyline(lineString, {
        style: {
            strokeColor: route.color,
            lineWidth: 6
        }
    });

    map.addObject(polyline);
});

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


Группировка транспортных объектов

При большом количестве линий удобно использовать объект H.map.Group.

const transportGroup = new H.map.Group();

transportGroup.addObject(busLine);
transportGroup.addObject(metroLine);
transportGroup.addObject(tramLine);

map.addObject(transportGroup);

Преимущества группировки:

  • централизованное управление объектами;
  • быстрое скрытие и отображение слоёв;
  • упрощение обработки событий.

Автоматическое позиционирование карты по маршруту

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

map.getViewModel().setLookAtData({
    bounds: transportLine.getBoundingBox()
});

Метод вычисляет минимальную область, содержащую весь маршрут, и корректирует масштаб карты.


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

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

Обработка клика

transportLine.addEventListener('tap', () => {
    console.log('Маршрут выбран');
});

Изменение стиля при выборе

transportLine.addEventListener('tap', () => {

    transportLine.setStyle({
        strokeColor: '#ff9900',
        lineWidth: 10
    });

});

После выбора линия становится толще и меняет цвет.


Отображение информации о маршруте

Часто требуется показывать сведения о маршруте при нажатии.

transportLine.addEventListener('tap', evt => {

    const bubble = new H.ui.InfoBubble(
        evt.target.getGeometry().extractPoint(0),
        {
            content: `
                <strong>Маршрут №12</strong><br>
                Тип: автобус
            `
        }
    );

    ui.addBubble(bubble);

});

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

  • номер маршрута;
  • тип транспорта;
  • расписание;
  • интервалы движения;
  • дополнительные сведения.

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

Для обозначения направления движения можно комбинировать линии с маркерами.

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

map.addObject(marker);

Маркер размещается в конечной точке маршрута и может содержать пользовательскую иконку в виде стрелки.


Масштабозависимое отображение транспортных линий

При изменении масштаба карты можно динамически изменять внешний вид маршрутов.

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

    const zoom = map.getZoom();

    transportLine.setStyle({
        strokeColor: '#0066ff',
        lineWidth: zoom > 14 ? 10 : 5
    });

});

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


Оптимизация отображения крупных транспортных сетей

При работе с сотнями маршрутов рекомендуется:

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

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


Комбинирование линий и остановок

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

const stopMarker = new H.map.Marker({
    lat: 50.4542,
    lng: 30.5340
});

map.addObject(stopMarker);
map.addObject(busLine);

В результате формируется полноценная схема маршрута, включающая:

  • траекторию движения транспорта;
  • остановочные пункты;
  • станции пересадки;
  • конечные станции;
  • направления движения.

Такой подход лежит в основе большинства современных транспортных карт, построенных на базе HERE Maps API.