Веб-разработка постоянно эволюционирует, и современный сайт уже трудно представить без интеграции с различными API. Один из самых полезных инструментов – это Google Maps API, который позволяет добавлять на сайт карты и осуществлять географические расчеты. В этой статье мы подробно рассмотрим, как интегрировать Google Maps API и калькулятор расстояний на JavaScript в ваш проект. Готовы? Поехали! 🚀
Шаг 1: Подключаем Google Maps API 🗺️
Первый шаг – это подключение Google Maps API к вашему проекту. Для этого нам потребуется загрузить скрипт с API ключом. В коде, который вы видите ниже, мы используем динамическую загрузку скриптов с помощью JavaScript. Это особенно полезно, если вы хотите оптимизировать загрузку вашего сайта.
<script src="https://maps.googleapis.com/maps/api/js?key=ВАШ_КЛЮЧ&libraries=places&loading=async&callback=initMap"></script> <script src="https://ваш_домен/wp-content/themes/astra-child/calculate.js"></script>
Важный момент: замените ВАШ_КЛЮЧ на ваш реальный API ключ от Google Maps. Также создайте файл calculate.js, в котором будет скрипт самого калькулятора. 🔑
Шаг 2: Инициализация карты и автозаполнение 🗺️✍️
Теперь, когда скрипты подключены, давайте разберем, как инициализировать карту и использовать автозаполнение для поиска городов. Это делается в функции initMap, которая вызывается после загрузки карты.
1. Инициализация карты
async function initMap() {
// Ожидаем полной загрузки окна
await new Promise(resolve => window.addEventListener('load', resolve));
// Получаем элементы DOM
const fromInput = document.querySelector('input[name="form_fields[from_city]"]');
const toInput = document.querySelector('input[name="form_fields[to_city]"]');
// Проверяем существование элементов DOM
if (!fromInput || !toInput) {
console.error('Не найдены необходимые элементы DOM');
return;
}
// Инициализация автодополнения
const options = { types: ["(cities)"] };
const fromAutocomplete = new google.maps.places.Autocomplete(fromInput, options);
const toAutocomplete = new google.maps.places.Autocomplete(toInput, options);
// Обработчики событий изменения местоположения
fromAutocomplete.addListener("place_changed", () => handleSelection());
toAutocomplete.addListener("place_changed", () => handleSelection());
}
Функция initMap делает следующее: она дожидается полной загрузки страницы и инициализирует элементы автозаполнения для полей ввода городов. При выборе города с помощью автозаполнения вызывается функция handleSelection, которая запускает расчеты расстояний. 🌆🚗
2. Расчет расстояния между городами
Когда пользователи выбирают города, нам нужно рассчитать расстояние между ними. Для этого используется DistanceMatrixService от Google Maps API. Этот сервис позволяет определить расстояние и время в пути между несколькими точками.
async function calculateDistance(from, to) {
const service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [from],
destinations: [to],
travelMode: "DRIVING",
unitSystem: google.maps.UnitSystem.METRIC,
},
(response, status) => {
if (status !== "OK") {
updateResult(`Ошибка: ${status}`);
updatePriceResult("");
} else {
const element = response.rows[0].elements[0];
if (element.status === "OK" && element.distance) {
const distanceValue = element.distance.value;
distanceKm = Math.round(distanceValue / 1000);
updateResult(distanceKm);
updatePriceResult();
} else {
updateResult("Не удалось определить расстояние");
updatePriceResult("");
}
}
}
);
}
Функция calculateDistance запрашивает данные о расстоянии от Google Maps API и обновляет поля с полученными результатами. Она также вызывает функцию updatePriceResult для обновления стоимости расчета. 📏💵
Шаг 3: Обновление результата и стоимости 💰
После того, как расстояние между городами было рассчитано, нам нужно обновить результаты на странице. Это включает в себя как расстояние, так и расчет стоимости. Ниже показаны функции для обновления этих данных:
1. Обновление расстояния
function updateResult(message) {
const resultDiv = document.querySelector(".distance-result-text");
if (resultDiv) {
resultDiv.textContent = `${message}`;
} else {
console.error("Элемент с классом distance-result не найден.");
}
}
Функция updateResult обновляет элемент на странице, показывающий расстояние между выбранными городами. 📍
2. Обновление стоимости
function updatePriceResult() {
const carSelect = document.querySelector("#form-field-type_car");
const bigCarSelect = document.querySelector("#form-field-type_bigcar");
const priceResultDiv = document.querySelector(".price-result-text");
if (priceResultDiv) {
const carValue = parseFloat(carSelect.value) || 1;
const bigCarValue = parseFloat(bigCarSelect.value) || 1;
const speedValue = parseFloat(document.querySelector('input[name="form_fields[radio_speed]"]:checked').value) || 0;
const totalPrice = distanceKm * carValue * bigCarValue + speedValue;
priceResultDiv.textContent = `${totalPrice.toFixed(2)}`;
} else {
console.error("Элемент с классом price-result не найден.");
}
}
Функция updatePriceResult вычисляет общую стоимость на основе расстояния, типа автомобиля и других факторов, и обновляет соответствующий элемент на странице. 💲
Шаг 4: Обработка событий 🛠️
Наконец, нам нужно настроить обработку событий для изменения значений в полях ввода и выборах, чтобы автоматически обновлять результаты. Для этого мы добавляем обработчики событий на элементы формы.
document.addEventListener('DOMContentLoaded', () => {
document.getElementById("form-field-radio_speed-0").checked = true;
carSelect.addEventListener('change', updatePriceResult);
bigCarSelect.addEventListener('change', updatePriceResult);
speedRadioButtons.forEach(radio => {
radio.addEventListener('change', updatePriceResult);
});
});
Этот код обеспечивает начальные значения и обновляет расчеты при изменении пользовательских выборов. 🎯
Готовый код:
<script src="https://maps.googleapis.com/maps/api/js?key=ВАШ_КЛЮЧ&libraries=places&loading=async&callback=initMap"></script>
<script src="https://energetikov.ru/wp-content/themes/astra-child/calculate.js"></script>
document.addEventListener('DOMContentLoaded', () => {
const formCalculate = document.querySelector('#distance_calculator_form');
if (formCalculate) {
function loadGoogleMapsAPI() {
return new Promise((resolve, reject) => {
if (typeof google !== 'undefined' && google.maps) {
resolve();
return;
}
const script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyCesW0FO_ppB6z1IltCPAVd9NE-yHCeaiY&libraries=places&loading=async&callback=initMap';
script.async = true;
script.defer = true;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
function loadCalculatorScript() {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = 'https://energetikov.ru/wp-content/themes/astra-child/calculate.js'; // Замените на путь к вашему файлу calculate.js
script.async = true;
script.defer = true;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
// Загрузить Google Maps API и затем скрипт калькулятора
loadGoogleMapsAPI().then(() => {
return loadCalculatorScript();
}).then(() => {
console.log('Калькулятор и API загружены успешно');
}).catch((error) => {
console.error('Ошибка при загрузке:', error);
});
}
});
document.addEventListener('DOMContentLoaded', () => {
document.getElementById("form-field-radio_speed-0").checked = true;
});
async function initMap() {
document.getElementById("form-field-radio_speed-0").checked = true;
// Ожидаем полной загрузки окна
await new Promise(resolve => window.addEventListener('load', resolve));
// Получаем элементы DOM
const fromInput = document.querySelector('input[name="form_fields[from_city]"]');
const toInput = document.querySelector('input[name="form_fields[to_city]"]');
const resultDiv = document.querySelector(".distance-result-text");
const priceResultDiv = document.querySelector(".price-result-text");
const carSelect = document.querySelector("#form-field-type_car");
const bigCarSelect = document.querySelector("#form-field-type_bigcar");
const resultDivHidden = document.querySelector("#form-field-distance_hidden");
const priceResultDivHidden = document.querySelector("#form-field-price_hidden");
const speedRadioButtons = document.querySelectorAll('input[name="form_fields[radio_speed]"]');
const formCalculate = document.querySelector('#distance_calculator_form');
// Проверяем существование элементов
if (!fromInput || !toInput || !resultDiv || !priceResultDiv || !carSelect || !bigCarSelect || !resultDivHidden || !priceResultDivHidden || !formCalculate || speedRadioButtons.length === 0) {
console.error('Не найдены необходимые элементы DOM');
return;
}
// Инициализация автодополнения
const options = { types: ["(cities)"] };
const fromAutocomplete = new google.maps.places.Autocomplete(fromInput, options);
const toAutocomplete = new google.maps.places.Autocomplete(toInput, options);
// Инициализация переменных
let fromCitySelected = false;
let toCitySelected = false;
let distanceKm = 0;
// Обработчики событий изменения местоположения
fromAutocomplete.addListener("place_changed", () => {
fromCitySelected = true;
handleSelection();
});
toAutocomplete.addListener("place_changed", () => {
toCitySelected = true;
handleSelection();
});
// Функция для расчета расстояния
async function calculateDistance(from, to) {
const service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [from],
destinations: [to],
travelMode: "DRIVING",
unitSystem: google.maps.UnitSystem.METRIC,
},
(response, status) => {
if (status !== "OK") {
updateResult(`Ошибка: ${status}`);
updatePriceResult("");
} else {
const element = response.rows[0].elements[0];
if (element.status === "OK" && element.distance) {
const distanceValue = element.distance.value;
distanceKm = Math.round(distanceValue / 1000);
updateResult(distanceKm);
updatePriceResult();
} else {
updateResult("Не удалось определить расстояние");
updatePriceResult("");
}
}
}
);
}
// Функция для обновления элемента с расстоянием
function updateResult(message) {
if (resultDiv) {
resultDiv.textContent = `${message}`;
} else {
console.error("Элемент с классом distance-result не найден.");
}
}
// Функция для обновления цены
function updatePriceResult() {
const lastOption = bigCarSelect.options[bigCarSelect.options.length - 1];
if (carSelect.selectedIndex === 0) {
if (priceResultDiv && fromCitySelected && toCitySelected) {
const carValue = parseFloat(carSelect.value) || 1;
const bigCarValue = parseFloat(bigCarSelect.value) || 1;
const speedValue = parseFloat(document.querySelector('input[name="form_fields[radio_speed]"]:checked').value) || 0;
const totalPrice = distanceKm * carValue * bigCarValue + speedValue;
priceResultDiv.textContent = `${totalPrice.toFixed(2)}`;
priceResultDivHidden.value = totalPrice.toFixed(2);
resultDivHidden.value = distanceKm;
}
} else {
bigCarSelect.selectedIndex = bigCarSelect.options.length - 1;
if (priceResultDiv && fromCitySelected && toCitySelected) {
const carValue = parseFloat(carSelect.value) || 1;
const speedValue = parseFloat(document.querySelector('input[name="form_fields[radio_speed]"]:checked').value) || 0;
const totalPrice = distanceKm * carValue + speedValue;
priceResultDiv.textContent = `${totalPrice.toFixed(2)}`;
priceResultDivHidden.value = totalPrice.toFixed(2);
resultDivHidden.value = distanceKm;
}
}
}
// Обработка выбора городов и вызов функции для расчета расстояния
function handleSelection() {
if (fromCitySelected && toCitySelected) {
const fromCity = fromInput.value;
const toCity = toInput.value;
calculateDistance(fromCity, toCity);
}
}
// Инициализация значений по умолчанию и обработчиков событий
const bigCarValueHiddenItem = () => {
if (carSelect.selectedIndex !== 0) {
bigCarSelect.selectedIndex = bigCarSelect.options.length - 1;
for (let i = 0; i < bigCarSelect.options.length; i++) {
bigCarSelect.options[i].disabled = i !== bigCarSelect.options.length - 1;
}
} else {
for (let i = 0; i < bigCarSelect.options.length; i++) {
bigCarSelect.options[i].disabled = false;
}
bigCarSelect.options[bigCarSelect.options.length - 1].disabled = true;
if (bigCarSelect.selectedIndex === bigCarSelect.options.length - 1) {
bigCarSelect.selectedIndex = 0;
}
}
};
document.addEventListener('DOMContentLoaded', () => {
document.getElementById("form-field-radio_speed-0").checked = true;
});
bigCarValueHiddenItem();
carSelect.addEventListener('change', bigCarValueHiddenItem);
carSelect.addEventListener("change", updatePriceResult);
bigCarSelect.addEventListener("change", updatePriceResult);
speedRadioButtons.forEach(radio => {
radio.addEventListener("change", updatePriceResult);
});
}
// Убедитесь, что функция initMap вызывается при загрузке страницы
window.onload = initMap;
Заключение 🎉
В этой статье мы рассмотрели, как интегрировать Google Maps API и реализовать калькулятор расстояний с помощью JavaScript. Мы подробно обсудили каждый шаг, от подключения API до реализации функций расчета и обновления результатов. Это поможет вам создать мощный инструмент для вашего сайта, который сможет рассчитывать расстояния и стоимость поездок на основе введенных данных. 🚀🌟