Привет, Хабр!
Думаю, что все знают про 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 Яндекс для работы с картами и реализована задача по построению маршрута. Документация предоставляет возможность понять, как работают различные методы и как можно применять их. Думаю, данный материал будет полезен начинающим разработчикам, у которых возникла потребность в реализации построении карт на основе текстовых представлений адресов.