Время прочтения: 5 мин.

Думаю, что все знают про YandexAPI, но знать недостаточно, надо применять. Сегодня разберу небольшую задачу, которая заключается в следующем:

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

Покажу одну из возможных реализаций на языке JavaScript, создам форму на HTML и приправлю все немножечко Bootstrap v5.

Что необходимо отобразить на странице для выполнения задачи:

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

Стоит отметить, что API работают только с ключом, который можно получить в личном кабинете разработчика Яндекс, там необходимо оформить бесплатный доступ к «JavaScript API и HTTP Геокодер». Расписывать процесс не буду, там легко разобраться.

Теперь программирование. Форма без применения стилей будет выглядеть посредственно, поэтому покажу конечный вариант с Bootstrap, чтобы не раздувать материал кодом, еще же на JavaScript писать. Реализация формы выглядит следующим образом:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Задача</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css"
          rel="stylesheet"
          integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx"
          crossorigin="anonymous">
</head>
<body>

    <form id="form" onsubmit="postRequest()">
        <p class="text-center">Тестовый образец!</p>

        <div class="route mb-3 d-flex flex-column">

            <label class="form-label">
                Откуда:
            </label>
            <input 
                id="labelPick"
                name="pick_up"
                type="text"
                class="form-control"
                onblur=""
                value=""
            >

            <label class="form-label">
                Куда:
            </label>
            <input 
                id="labelDrop validationServer02"
                name="drop_to"
                type="text"
                class="form-control"
                onblur=""
                value=""
            >

        </div>

        <button 
            id="btnRequest"
            type="submit"
            class="btn btn-primary"
        >
            Submit
        </button>
    </form>

    <div class="containerCards">
        <div class="card mb-3">
            <div 
                id="mapWay"
                class="card-img-top"
                style="width:100%; height:350px;"
            >
            </div>
            <div class="card-body">
                <p id="departure" class="card-text">
                    Откуда: 
                </p>
                <p id="destination" class="card-text">
                    Куда: 
                </p>
                <p class="card-text">
                    <small class="text-muted">
                        Дата создания: 
                    </small>
                </p>
            </div>
        </div>
    </div>
</body>
</html>

В коде можно заметить, что в input стоит метод onblur. Его применение будет вызываться, когда фокус с поля будет снят. Для чего же это необходимо? Для вызова JavaScript, чтобы получить корректный адрес, ведь человек может ошибиться в написании адресов, чтобы избежать это вытащу результат из геокодера предоставляемый API, и заменю на него значение поля ввода.

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

Реализация скрипта будет выглядеть следующим образом:

ymaps.ready(getcoords);
    form.addEventListener('submit', getFormValue);

    function getFormValue(event) {
        event.preventDefault();
    }
    // функция получения корректного адреса
    function getcoords(value, inputID){
        // очистка текста от лишних символов
        let check = value.replace(/[!@#$%^&*()+]/g, ' ').replace(/\s+/g, ' ').trim();
        // проверка корректности введенного адреса
        if ((check !== "") && (check.length > 10)) {
            // запрос в геокодер
            let myGeo = new ymaps.geocode(check);
            // получение ответа
            myGeo.then(
                function (res) {
                    // заменяем текст на результат геокодера убрав страну
                    document.getElementById(idInput).value = res.geoObjects
                        .get(0)["properties"]["_data"]["text"]
                        .slice(8,);
                }
            );
        // в случае ошибки выводим сообщение
        }else{
            alert("Введите корректное значение!")
        }
    }

На этом этапе работа с полями ввода закончена, при вводе адреса скрипт меняет на адрес, который хранится в базе данных Яндекса и является корректным.

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

  • центральная точка в координатах;
  • зум.

Говоря про JavaScript, каждый элемент является объектом с набором функций, в данном случае это Map. В него передаются id элемента в котором будет располагаться карта, а также словарь из двух ключей со значениями, перечисленными выше. После из объекта вызывается метод route, который позволяет построить путь от точки до точки. В него необходимо передать список, в котором будет храниться информация о точках отправления и прибытия.   

Список может хранить в себе следующую информацию о точке:

  • текстовый адрес;
  • координаты долготы и широты.

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

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

Чуть не забыл, крайне важно выполнить позиционирование карты на маршруте, чтобы его возможно было увидеть. Для этого есть метод setBounds у объекта Map, который принимает координаты точек, но основе которых центрует карту на точке между ними. Также можно передать настройки позиционирования карты, используя 2 параметра:

  • checkZoomRange – параметр, который определяет возможно ли установить коэффициент масштабирования, указанный пользователем;
  • zoomMargin – параметр, который определяет отступ от границ области карты.

Тогда код будет выглядеть следующим образом:

ymaps.ready(loadMapData);

    // функция для запуска отрисовки карт 
    function loadMapData() {
        let cards = Array.from(document.getElementsByClassName("card mb-3"))
        for (card in cards) {
            let wayId = cards[card].firstElementChild.id;
            let dep = cards[card].innerText.split('\n')[2].slice(8,);
            let dest = cards[card].innerText.split('\n')[3].slice(6,);
            createWay(wayId, dep, dest);
        }
    }
    // функция создания карты
    function createWay(divId, departure, destination) {
        var myMap = new ymaps.Map(divId,{
                center: [52, 104],
                zoom: 13
        });
        // получение точек на карте
        ymaps.route([
                departure,
                destination
        ]).then(
            // доп функция для отображения меток и позиционирования карты
            function (route) {
                // получение данных по адресам
                myMap.geoObjects.add(route);
                // получение всех точек маршрута
                var points = route.getWayPoints();
                var lastPoint = points.getLength() - 1;
                // Стиль меток – красный лого и авто выравнивание ширины
                points.options.set('preset', 'twirl#redStretchyIcon');
                // Создание контента на первой и последней точках 
                points.get(0).properties.set('iconContent', 'Точка отправления');
                points.get(lastPoint).properties.set('iconContent', 'Точка прибытия');
                // позиционирование карты
                myMap.setBounds([points.get(0).geometry._coordinates,
                                points.get(lastPoint).geometry._coordinates], {
                    checkZoomRange: true,
                    zoomMargin: 10
                });
            },
            // в случае ошибки
            function (error) {
                alert('Возникла ошибка: ' + error.message);
            }
        );
    }

Вставку адресов в карточку реализовать просто, думаю проблем не возникнет.

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