Калькулятор-расстояний-google_api

Как интегрировать Google Maps API и калькулятор на JavaScript (форма Elementor)

Веб-разработка постоянно эволюционирует, и современный сайт уже трудно представить без интеграции с различными 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 до реализации функций расчета и обновления результатов. Это поможет вам создать мощный инструмент для вашего сайта, который сможет рассчитывать расстояния и стоимость поездок на основе введенных данных.  🚀🌟

Содержимое
Вам может быть интересно

Скрол к блоку на странице (без перекрытия)

Маска на поле телефон

Форма Elementor

Let's work together!