Построение маршрута на OpenLayers 3

Построение маршрута на OpenLayers 3

Если вы программист, работающий в сфере ГИС, то велика вероятность однажды встретить такую задачу, как построение маршрута. Снова упомяну, что OpenLayers 3 — это только библиотека для работы с картой на клиентской стороне, с ней в комплекте не идет сервис построения маршрута. А значит, все нужно сделать самим.

Конечно, не совсем все придется делать самим… Нам не понадобится наполнять базу данных адресов, строить графы дорог, писать на их основе логику поиска маршрутов а так же разрабатывать операционную систему — готовых сервисов хватает. Нужно лишь отправить запрос с начальной и конечной точками, прочитать ответ и отобразить на карте результат. Я воспользовался одним из сервисов на основе данных OSM под названием OSMR — Open Source Routing Machine. Кроме того, нам понадобится сервис определения адреса по координатам (обратное геокодирование), чтобы начальная и конечная точки были не малоинформативными Точка1 и Точка2, а конкретными адресами. Итак, начнем.

Ранее мы рассматривали, как сделать свой контрол, воспользуемся этим материалом снова. Только на этот раз не будем создавать все HTML-элементы через createElement , а определим все в разметке, так проще и быстрее:

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

Еще нужно создать слой, в котором будем отрисовывать маркеры. В OpenLayers 3 маркер — это точка с настроенным стилем, где указывается иконка:

Стиль iconStyle задает иконку markerStart.png для каждой точки слоя. Иконка будет находится над точкой и выровнена по горизонтали — за это отвечает anchor : [0.5, 1] . Если задать anchor : [0.5, 0.5] , точка будет находится прямо в центре иконки, anchor : [0, 0] — точка в левом верхнем углу иконки. Проблема в том, что у всех маркеров будет одна и та же иконка markerStart.png, а нам нужно, чтобы иконки отличались для начальной и конечной точки. Для достижения этой цели мы используем не статический стиль, а функцию генерации стиля:

Данный механизм даёт нам возможность устанавливать разные стили в зависимости от текущего объекта и разрешения (приближения). Это дает массу возможностей — например, можно отображать подписи только на большом приближении за счет параметра resolution , чтобы они не смешивались в кашу при отдалении. Или можно задать разный цвет заливки для полигонов в зависимости от атрибута. В нашем случае мы будем брать путь к маркеру из атрибутов объекта — то есть каждый объект будет сам указывать, с помощью какой иконки он будет отображен на карте. Функция styleFunc передается в конструктор слоя вместо iconStyle .

Все готово к установке маркеров на карту — слой создан, стиль подготовлен. Осталось написать код для добавления маркера при клике на карте в функции _processClick :

Условие довольно сложное, но это лишь для того, чтобы не принуждать пользователя кликать в поля ввода для установки маркера. Если при открытии просто нажать два раза на каре, то установится точка отправления, а затем точка назначения. Можно установить фокус на поле ввода для точки назначения и указать сначала ее, а следующим кликом установится незаполненная точка отправления. Сам маркер создается в функции _createPoint , где указываются координаты точки и иконка маркера.

Следующим шагом будет заполнение адресов в полях ввода и построение маршрута. Заполнение адреса происходит при установке маркера:

Функция fillAddress принимает два параметра — координаты, по которым нужно определить адрес, и поле ввода, которое нужно заполнить ответом от сервера. В качестве сервиса определения адреса я взял nominatim.openstreetmap.org — тот же, что и на OSMR. В запросе отправляется широта и долгота, а возвращается JSON, в поле display_name которого приходит полный адрес:

И, наконец, само построение маршрута. На сайте OSRM построение маршрута снабжается массой информации — вплоть до каждого поворота и длины каждого отрезка пути. Нам не нужно столько деталей, а нужна лишь суммарная информация о маршруте. К счастью, в сервисе присутствует масса настроек для управления выводом информации, которые описаны в документации API. Нужно лишь установить параметр steps=false , чтобы отключить подробный вывод, и добавить параметр overview=true , чтобы сервис возвращал обобщенную информацию. Стоит еще отметить, что сервис возвращает геометрию в компактном формате закодированной полилинии (при желании можно настроить ответ на GeoJSON с помощью параметра geometries=geojson), будем использовать для декодирования соответствующий формат OL3 — ol.format.Polyline

Готово! Мы получили относительно несложное построение маршрута. «Несложное», потому что нельзя двигать точки отправления и прибытия на карте, нельзя добавлять промежуточные точки, нет подсказок над маркерами и прочих удобств. Но статья итак получилась довольно объемной и нагружать ее сверх меры я не стал. Тем более получилось довольно законченное ядро, отталкиваясь от которого можно сделать своё построение маршрута и совершенствовать его до изнеможения 🙂 .

📎📎📎📎📎📎📎📎📎📎