Строим маршруты с помощью OpenStreetMap, OSRM и Leaflet

в 15:36, , рубрики: javascript, OpenStreetMap

Привет, %username%! Хочу написать маленькую статейку о том, как с помощью OpenStreetMap, OSRM и Leaflet прокладывать маршруты в своем проекте. Рассказывать что представляют из себя вышеуказанные технологии я не буду — на хабре о них писалось не раз уже, статья будет маленькая и только по делу. Итак, если вы хотите строить маршруты — прошу под кат.

image

Итак, приступим. Для работы нам понадобится JQuery и Leaflet. Последний можно взять на официальном сайте — leafletjs.com
При желании можно использовать CDN (от себя отмечу — довольно быстро грузится).

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />

<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>

Далее нам понадобится контейнер, куда будет загружаться карта. Создаем div и даем ему идентификатор map

<div id="map"></div>

При необходимости ему можно задавать ширину/высоту, использовать во всплывающих окнах и пр.
Теперь непосредственно инициализация — привязываем карту к нашему div'у.

var map = L.map('map');

После этого в наш div загружается карта. Но что в данном случае подгрузит Leaflet? Явно не тот город, где мы находимся. Для исправления этого пишем следующий код:

map.setView([55.7422, 37.5719], 11);

Данная конструкция загрузит нам карту Москвы(координаты нужно вставлять в очередности LatLng, zoom), где zoom — масштаб. Ах да, чуть не забыл — нам нужно указать, откуда брать изображения для карты. Источники могут быть самые разные, от официального сайта до собственного сервера. Возьмем официальный сайт:

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map);

На этом этапе у нас в наш div загружается карта нужного нам города. Теперь приступим к построению маршрутов. Для начала будем добавлять по клику на карте маркер. Всего маркеров будет 2 — для начала пути и конца, не будем пока делать маршрутизацию с несколькими точками. Итак, нам нужно обрабатывать событие 'click' по карте. У меня это реализовано так:

map.on('click', function(e) {
        onMapClick(e);
    });
function onMapClick(e) {
        if (loc1 == null) {
            loc1 = new L.marker(e.latlng, {draggable: 'true'});
            loc1.on('dragend', function(event) {
                //отправляем запрос маршрута
            });
            map.addLayer(loc1);
        }
        else if (loc2 == null) {
            loc2 = new L.marker(e.latlng, {draggable: 'true'});
            loc2.on('dragend', function(event) {
                //отправляем запрос марурута
            });
            map.addLayer(loc2);
            //отправляем запрос маршрута
        }
    }
    ;

После клика по карте функция onMapClick проверяет, существуют ли точки loc1 и loc2. Если существуют обе точки — отслеживается только перемещение маркера по карте ('dragend'). Само перетаскивание включается при помощи параметра draggable: 'true'. Маркеры есть, перетаскивание отслеживается, осталось только прикрутить прорисовку маршрута. Куда отправлять запрос — решать Вам, можно использовать OSRM (и я вам это настоятельно советую, бесплатный инструмент с высокой скоростью работы). Я же использую собственный сервер, который мне отдает результат polyline-строке. В интернете есть готовая реализация для всех ЯП по декодированию этой строки в массив значений. Как это реализовать в вашем случае — решать только Вам. У меня декодирование выполняется с помощью php и результат возвращается в виде массива координат. Итак, метод отправки запросов и самой прорисовки маршрутов:


var polyline;

    function sendPost() {
        if (loc2 != null && loc1 != null) {
            var p1 = loc1.getLatLng(),
                    p2 = loc2.getLatLng();
            $.post(
                    //куда шлем запрос,
                    {l1: p1.lat + ',' + p1.lng, l2: p2.lat + ',' + p2.lng},
            function(data) {
                if (data) {
                    if (polyline) {
                        map.removeLayer(polyline);
                    }
                    var points = data;
                    polyline = new L.polyline(points, {color: 'red'});
                    map.addLayer(polyline);
                    map.fitBounds(polyline.getBounds());
                }
            },
                    "json"
                    );
        }
    }

Признаюсь сразу — javascript знаю крайне ужасно, но Вы это уже, наверное, поняли. Но продолжим. Задаем переменную polyline, которую потом будем использовать для создания линии маршрута. Линию будем добавлять новым слоем для того, чтобы при перетаскивании можно было удалить старый маршрут. При успешно выполненном запросе идет проверка — существует уже слой или нет. Если существует (т.е. есть уже маршрут) — удаляется и строится новый.

Вот, в принципе, и все. Прошу опытных программистов сильно не ругаться — статья больше ориентирована на новичков, таких как я. При выполнении данной задачи я столкнулся с отсутствием в сети примеров для построения маршрутов с помощью данной библиотеки и прочих мелких нюансов, с которыми я столкнулся. С радостью отвечу на все ваши вопросы и добавлю то, что по вашему мнению я упустил.

Автор: HunterNNm

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js