При разработке картографических приложений часто возникает необходимость отображать маршруты общественного транспорта, железнодорожные пути, трамвайные линии, линии метро, автобусные маршруты и другие линейные объекты транспортной инфраструктуры. В экосистеме 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
}
});
Результат:
Для визуального выделения перегруженных участков карты применяется прозрачность.
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 может возвращать геометрию пути между остановками или станциями.
После получения маршрута необходимо преобразовать его геометрию в
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);
Преимущества такого подхода:
На карте нередко отображается целая транспортная сеть.
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
});
});
Подобная техника повышает читаемость карты на различных уровнях приближения.
При работе с сотнями маршрутов рекомендуется:
Особенно важна оптимизация при отображении городских транспортных сетей, содержащих тысячи сегментов дорог и десятки маршрутов общественного транспорта.
Наиболее информативное представление транспортной сети достигается совместным использованием линий и маркеров остановок.
const stopMarker = new H.map.Marker({
lat: 50.4542,
lng: 30.5340
});
map.addObject(stopMarker);
map.addObject(busLine);
В результате формируется полноценная схема маршрута, включающая:
Такой подход лежит в основе большинства современных транспортных карт, построенных на базе HERE Maps API.