Геолокация

Примечание: Раньше пример работал на любой странице, теперь методы определения местоположения в целях безопасности работают только через HTTPS.

Мы привыкли, что широта и долгота указываются в градусах/минутах/секундах. Однако, при программировании чаше используются десятичные значения. Можно написать отдельную функцию для перевода градусов в десятичное значение:


function degreesToDecimal(degrees, minutes, seconds) {
    return degrees + (minutes / 60.0) + (seconds / 3600.0);
}

Браузер узнаёт координаты по GPS, IP-адресу, вышкам сотовой связи, точками доступа WiFi. Не забывайте, что браузер может быть запущен не только на настольном компьютере, но и на сотовом телефоне. У каждого способа различная степень точности.

Пользователь должен дать своё согласие на использование определения своего местоположения.

Объект window.navigator.geolocation имеет три метода для работы с геолокацией

  • getCurrentPosition
  • watchPosition
  • clearWatch

Для проверки поддержки геолокации браузером, можно использовать следующий код:


if (window.navigator && window.navigator.geolocation) {
   // Ваш код для определения местоположения
} else {
   // Не поддерживается
}

Напишем сценарий определения местоположения в отдельном файле my_location.js и подключем его к странице.


<script src="my_location.js"></script>

А на странице добавим контейнер для вывода информации - <div id="location">.

Ваши координаты

Содержимое сценария.


// Вызываем функцию, как только браузер закончит загрузку страницы
window.onload = getMyLocation;

function getMyLocation() {
    if (navigator.geolocation) { // если браузер поддерживает Geolocation
        navigator.geolocation.getCurrentPosition(displayLocation);
    } else {
        alert("Определение местоположения не поддерживается");
    }
}

function displayLocation(position) {
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
    
    var div = document.getElementById("location");
    div.innerHTML = "Ваши координаты. Широта: " + latitude + ", Долгота: " + longitude;
}

При первом запуске браузер запросит разрешение на использование данных о местоположении. При согласии вы увидите свои координаты на экране. Иногда это занимает несколько секунд.

Метод getCurrentPosition() имеет три параметра, два последних из них являются опциональными.


getCurrentPosition(successHandler, errorHandler, options)

Функция successHandler вызывается, если браузер определил местоположение.

Функция errorHandler вызывается, если произошла какая-то ошибка при определении местоположения.

Параметр options позволяет сконфигурировать Geolocation.

При определении местоположения мы получаем объект position, который обладает свойством coords. В свою очередь данный объект содержит свойства latitude и longitude.

Если вы желаете отлавливать ошибки, то используйте код с соответствующим параметром.


navigator.geolocation.getCurrentPosition(displayLocation, displayError);

function displayError(error) {
    var errorTypes = {
        0: "Unknown error",
        1: "Permission denied by user",
        2: "Position is not available",
        3: "Request timed out"
    }
    
    var errorMessage = errorTypes[error.code];
    if (error.code == 0 || error.code == 2) {
        errorMessage = errorMessage + " " + error.message;
    }
    
    var div = document.getElementById("location");
    div.innerHTML = errorMessage;
}

При ошибках с номерами 0 или 2 в свойстве error.message находится дополнительная информация, которую можно вывести на экран.

Ошибка 0 - общая ошибка, которая выводится, когда ни одна из остальных ошибок не подходит.

Ошибка 1 - пользователь не разрешил определять своё местоположение.

Ошибка 2 - браузер пытался, но не смог получить координаты. Выводит дополнительную информацию.

Ошибка 3 - истекло время ожидания, в течение которого можно было определить местоположение.

Измеряем расстояние

Научившись находить своё местоположение, можно перейти к следующему этапу - измерить расстояние от своей точки до заданного места.

Добавим ещё один блок div:


<div id="location2" style="border: solid;">
Ваши координаты
</div>

<div id="distance" style="border: solid;">
Расстояние от Красной площади
</div>

Ваши координаты
Расстояние от Красной площади

В файл my_location.js добавим новые функции.


function computeDistance(firstCoords, secondCoords) {
    var firstLatRad = degreesToRadians(firstCoords.latitude);
    var firstLongRad = degreesToRadians(firstCoords.longitude);
    var secondLatRad = degreesToRadians(secondCoords.latitude);
    var secondLongRad = degreesToRadians(secondCoords.longitude);
    
    var radius = 6371; // радиус Земли в километрах
    var distance = Math.acos(Math.sin(firstLatRad) * Math.sin(secondLatRad) +
            Math.cos(firstLatRad) * Math.cos(secondLatRad) * 
            Math.cos(firstLongRad - secondLongRad)) * radius;
            
    return distance;        
}

function degreesToRadians(degrees) {
    var radians = (degrees * Math.PI)/180;
    return radians;
}

В первой функции указываем две точки с координатами в параметрах и получаем расстояние между ними в километрах. Вторая функция переводит градусы в радианы.

Теперь надо указать координаты нужной точки, например, Красной площади:


var RedSquareCoords = {
    latitude: 55.753905,
    longitude: 37.620803
};

Добавьте этот код в начало файла с сценарием.

Напишем вторую версию функции displayLocation():


function displayLocation2(position) {
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
    
    var div = document.getElementById("location2");
    div.innerHTML = "Ваши координаты. Широта: " + latitude + ", Долгота: " + longitude;
    
    var km = computeDistance(position.coords, RedSquareCoords);
    var distance = document.getElementById("distance");
    distance.innerHTML = "До Красной площади " + km + " километров";
}

Если метод getCurrentPosition() вычисляет координаты один раз, то метод watchPosition() следит за перемещениями постоянно.

Работа с ним схожа:


watchPosition(successCallback [, errorCallback [, options]])

Метод clearWatch() останавливает мониторинг перемещения, вызванный методом watchPosition().

Реклама