Наш чат в Telegram для обмена идеями, проектами, мыслями, людьми в сфере ИТ г.Ростова-на-Дону: @it_rostov

Геолокация - определение местоположения


Забегая вперед, для нежелающих вникать в детали, готовый пример использования Geolocation API:

if (navigator.geolocation) {
    var location_timeout = setTimeout("geolocFail()", 10000);

    navigator.geolocation.getCurrentPosition(function(position) {
        clearTimeout(location_timeout);

        var lat = position.coords.latitude;
        var lng = position.coords.longitude;

        alert(lat + " , " + lng);

    }, function(error) {
        clearTimeout(location_timeout);
        geolocFail();
    },
        {
            maximumAge:Infinity,
            timeout:Infinity,
            enableHighAccuracy:false
        });
} else {
    geolocFail();
}
function geolocFail(){
    alert("Ваш браузер не поддерживает гео-локацию");
}

Geolocation API основывается на новом свойстве глобального объекта navigator — navigator.geolocation:

navigator.geolocation.getCurrentPosition(
	success,
	fail,
	{maximumAge:60000, timeout:5000, enableHighAccuracy:true}
);

Указание атрибутов в третьем параметре - дело добровольное:

  • enableHighAccuracy. Значение true указывает браузеру попытаться получить как можно более точное значение данных о местоположении посетителя страницы сайта (широты, долготы и высоты); при этом, однако, процесс получения данных может потребовать больше времени, а энергопотребление компьютера может возрасти. Значение false этого параметра затребует у браузера обычные данные о местоположении, которые могут оказаться не очень точными. Значение по умолчанию - false.
  • timeout - задаёт таймаут, в течении которого должны быть получены данные о местоположении, в виде целого числа в миллисекундах. Если указать значение 0 или отрицательное значение, система должна сразу же выдать данные о местоположении; в противном случае возникнет ошибка. Если указать значение Infinity (математическая "плюс бесконечность"), на получение данных о местоположении будет отведено столько времени, сколько потребуется. Значение по умолчанию - Infinity.
  • maximumAge - задаёт таймаут, в течение которого полученные сведения о местоположении будут кэшироваться системой (таймаут кэширования). То есть, если мы запросим сведения о местоположении, а потом, пока таймаут кэширования ещё не истёк, сделаем это ещё раз, система вернёт нам кэшированные сведения. Кэширование данных о местоположении позволяет сэкономить энергию батарей в портативных компьютерах.
    Значение этого таймаута указывается в виде целого числа в миллисекундах. Если указать значение 0 или отрицательное значение, система вообще не будет кэшировать данные о местоположении, а станет при каждом запросе получать их заново. Если же указать значение Infinity, данные о местоположении будут храниться в кэше всегда, и именно они будут возвращаться при запросе (например,вам нужно знать только город пользователя). Значение по умолчанию - 0 (то есть кэширование отключено).

Браузер без разрешения пользователя не передаст данные о месторасположении на удаленный сервер. В разных браузерах такой вопрос к пользователю может выглядеть по разному, например, в Firefox — это будет всплывающая панель вверху окна.

Вызываемая функция получает один параметр — объект с двумя свойствами: coords и timestamp. Timestamp — это дата и время, при которых было произведено определение месторасположения. Определение этих свойств происходит асинхронно. Нельзя заранее предугадать когда точно это произойдет. Для пользователя это может означать некоторую задержку, потому что нужно сначала прочитать панель и убедится, что пользователь дал разрешение на определение координат, затем может потребоваться время на подключение GPS устройства к спутнику и так далее. Объект coords имеет свойства latitude (широта) и longitude (долгота) — это и есть информация о физическом положении на земном шаре. Свойства объекта приведены ниже:

Свойство Тип Примечание
coords.latitude double Широта, десятичные градусы
coords.longitude double Долгота, десятичные градусы
coords.altitude double или null метров над референц-эллипсоидом (уровнем моря)
coords.accuracy double Погрешность в метрах
coords.altitudeAccuracy double или null Погрешность высоты над уровнем моря в метрах
coords.heading double или null Направление устройства в градусах по часовой стрелке относительно Северного полюса (0 = север, восток = 90, юг = 180, запад = 270)
coords.speed double или null Скорость движения в метрах в секунду
timestamp DOMTimeStamp Время получения информации, объект Date()

Гарантировано будут присутствовать только три свойства: coords.latitude, coords.longitude и coords.accuracy. Работоспособность остальных зависит от используемого пользователем устройства. Если данное свойство не поддерживается — вернется 0. Свойства heading и speed вычисляются на основании изменения положения пользователя, если, конечно, это возможно.

Второй аргумент для функции getCurrentPosition() для вызова обработчика ошибок:

Функция обработки ошибок с объектом PositionError, у которого имеются следующие свойства:

Свойство Тип Примечания
code short пронумерованные значения
message DOMString не предназначен для конечных пользователей

Свойство code принимает одно из следующих значений:

  • PERMISSION_DENIED (1) — когда пользователь не разрешает определение месторасположения;
  • POSITION_UNAVAILABLE (2) — если перебои с сетью или нет связи со спутником;
  • TIMEOUT (3) — если сеть работает плохо и на вычисление координат пользователя уходит слишком много времени. Что значит «слишком много»? Об этом расскажу позже;
  • UNKNOWN_ERROR (0) — какая-либо другая ошибка.

Пример :

function (err)
{
  var mess;
  switch (err.code) {
    case err.PERMISSION_DENIED:
      mess = "Посетитель не дал доступ к сведениям о местоположении";
      break;
    case err.POSITION_UNAVAILABLE:
      mess = "Невозможно получить сведения о местоположении";
      break;
    case err.TIMEOUT:
      mess = "Истёк таймаут, в течение которого должны быть получены данные о местоположении";
      break;
    default:
      mess = "Возникла ошибка '" + err.message + "' с кодом " + err.code;
  }
}

Функция getCurrentPosition() имеет необязательный третий аргумент, объект PositionOptions. Все свойства являются необязательными, вы можете задать любой, все или ни одного.

Объект PositionOptions
Свойство Тип Значение по умолчанию Замечание
enableHighAccuracy boolean false Если true, то высокая точность определения местоположения, но получение может занять длительное время
timeout long Нет В миллисекундах
maximumAge long 0 В миллисекундах

Свойство enableHighAccuracy делает именно то, как и звучит. Если оно установлено как true, устройство поддерживает свойство и пользователь соглашается указать свое местоположение, то устройство попытается обеспечить высокую точность. Оба телефона iPhone и Android имеют отдельные разрешения для низкой и высокой точности позиционирования, поэтому не исключено, что вызов getCurrentPosition() с enableHighAccuracy:true не получится, а вызов enableHighAccuracy:false удастся.

Свойство timeout это количество миллисекунд, которое веб-приложение будет ожидать для получения положения. Таймер не начинает отсчет, пока пользователь не даст разрешение на попытку вычислить его положение. Он следит не за пользователем, а за сетью.

Свойство maximumAge позволяет устройству отвечать немедленно из закэшированной позиции. Например, вы обращаетесь к getCurrentPosition() в первый раз, пользователь соглашается, и ваша функция успешно возвращает положение вычисленное ровно в 10:00. Ровно через минуту, в 10:01 вы вызываете getCurrentPosition() снова установив свойство maximumAge в 75000.

navigator.geolocation.getCurrentPosition(
  success_callback, error_callback, {maximumAge: 75000}); 

Вы тем самым говорите, что вам необязательно знать текущее положение пользователя. Вы были бы рады знать, где он был 75 секунд назад (75000 миллисекунд). Устройство знает, где пользователь был 60 секунд назад (60000 миллисекунд), так как оно рассчитало место после первого вызова getCurrentPosition(). Поэтому устройство не будет пересчитывать текущее местоположение пользователя. Оно вернет ту же информацию, что и в первый раз: ту же широту и долготу, ту же точность и то же время (10:00).

Прежде чем вы запросите местоположение пользователя, вы должны подумать о том, какая точность вам требуется, и установить соответствующее enableHighAccuracy. Если вам необходимо найти место еще раз, вы должны подумать о том, какая старая информация может пригодиться и установить соответствующее maximumAge. Если требуется искать локацию постоянно, то getCurrentPosition() не для вас, необходимо перейти на watchPosition().

Функция watchPosition() имеет ту же структуру что и getCurrentPosition(). Она содержит две функции, одна требуется для успеха, вторая для ошибок, также может иметь необязательный объект PositionOptions, он имеет те же свойства, о которых вы узнали ранее. Разница в том, что ваша функция будет вызываться каждый раз при смене местоположения пользователя. Нет необходимости постоянного опроса позиции, устройство само определит оптимальный интервал опроса и вызовет функцию при изменении положения пользователя. Вы можете использовать эту возможность для обновления видимым маркеров на карте, предоставления инструкции, куда идти дальше или чего-нибудь еще. Это полностью зависит от вас.

Сама функция watchPosition() возвращает число, которое следует где-то хранить. Если вы хотите остановить слежение за положением пользователя, то можете вызвать метод clearWatch(), передать ему это число и устройство остановит вызов функции. Если вы когда-либо использовали функции setInterval() и clearInterval() в JavaScript, то это работает точно так же.

"Подписка" на получение сведений о местоположении

А ещё Geolocation API позволяет "подписаться" на постоянное получение сведений о местоположении. Это может пригодиться при разработке навигационных веб-приложений, предназначенных для мобильных устройств; в результате такое приложение сможет постоянно отслеживать изменение местоположения устройства.

Чтобы выполнить "подписку" на постоянное получение данных о местоположении, следует воспользоваться методом watchPosition объекта Geolocation. Формат его вызова таков:

window.navigator.geolocation.watchPosition(
    функция, которая будет вызвана каждый раз в случае успешного определения местоположения[,
    функция, которая будет вызвана каждый раз в случае возникновения ошибки при определении местоположения[,
    дополнительные параметры]]
);

Этот метод принимает те же параметры, что и знакомый нам метод getCurrentPosition.

Метод watchPosition возвращает особую целочисленную величину, называемую идентификатором "подписки". Этот идентификатор можно сохранить в переменной для отмены "подписки" на получение данных о местоположении. Если мы не собираемся отменять "подписку", идентификатор, возвращённый методом watchPosition, можно проигнорировать.

var iIdent = window.navigator.geolocation.watchPosition(
function (p)
{
  . . .
},
function (err)
{
  . . .
});

При первом вызове метода watchPosition сразу же запустится операция по получению текущего местоположения. Если она увенчается успехом, будет вызвана функция, переданная данному методу первым параметром, в противном случае - функция, переданная вторым параметром. Как видим, всё то же самое, что и в случае метода getCurrentPosition.

В дальнейшем, пока действует "подписка", система будет время от времени проверять, изменилось ли местоположение компьютера или мобильного устройства. (Интервал проверки зависит от характеристик аппаратной части компьютера или устройства и системных настроек). Если во время очередной проверки удалось получить местоположение, и это местоположение отлично от того, что было получено ранее, снова будет вызвана функция, переданная первым параметром методу watchPosition. Если же во время проверки возникла ошибка, будет вызвана функция, переданная этому методу вторым параметром.

Выполненную ранее "подписку" на получение информации о местоположении можно отменить. Для этого применяется метод clearWatch объекта Geolocation. В качестве единственного параметра он принимает идентификатор "подписки", которую нужно отменить. Результата он не возвращает.

window.navigator.geolocation.clearWatch(iIdent);

Согласно правилам безопасности, Google Chrome не позволит ненадёжным хостам (http://) запускать Geolocation API. Так что вам придётся установить SSL сертификат на ваш домен.

Обновлять мое местоположение на карте Яндекса по API

<script src="https://api-maps.yandex.ru/2.1/?load=package.full&lang=ru-RU" type="text/javascript"></script>
<script>
// Создание экземпляра карты и его привязка к контейнеру с заданным id ("map")
var map = new ymaps.Map('map', {
    // При инициализации карты, обязательно нужно указать
    // ее центр и коэффициент масштабирования
    center: geometry[0],
    zoom: 17,
    controls: [/*'geolocationControl'*/]
},{suppressMapOpenBlock:true});

// подписываюсь на получение местоположения пользователя
navigator.geolocation.watchPosition(function (position) {
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
    var myPlacemark = new ymaps.Placemark([latitude, longitude], {}, {preset: "islands#geolocationIcon"});
    map.geoObjects.add(myPlacemark);
    // Спозиционируем карту так, чтобы на ней были видны все объекты.
    map.setBounds(map.geoObjects.getBounds());

});
</script>
<div id="map" style="width:100%; height:400px"></div>

Обновлять мое местоположение на карте Google по API

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?v=3&sensor=false&language=en"></script>
<script>
    var map,
        currentPositionMarker,
        mapCenter = new google.maps.LatLng(12.345, 12.345);

    function initializeMap()
    {
        map = new google.maps.Map(document.getElementById('map'), {
            zoom: 18,
            center: mapCenter,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        });
    }

    function locError(error) {alert("Текущее местоположение не найдено!");}

    function setCurrentPosition(pos) {
        currentPositionMarker = new google.maps.Marker({
            map: map,
            position: new google.maps.LatLng(
                pos.coords.latitude,
                pos.coords.longitude
            ),
            title: "Текущее местоположение"
        });
        map.panTo(new google.maps.LatLng(
            pos.coords.latitude,
            pos.coords.longitude
        ));
    }

    function displayAndWatch(position) {
        setCurrentPosition(position);
        watchCurrentPosition();
    }

    function watchCurrentPosition() {
        var positionTimer = navigator.geolocation.watchPosition(
            function (position) {
                setMarkerPosition(
                    currentPositionMarker,
                    position
                );
            });
    }

    function setMarkerPosition(marker, position) {
        marker.setPosition(
            new google.maps.LatLng(
                position.coords.latitude,
                position.coords.longitude)
        );
    }

    function initLocationProcedure() {
        initializeMap();
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(displayAndWatch, locError);
        } else {
            alert("Ваш браузер не поддерживает Geolocation API!");
        }
    }

    $(document).ready(function() {
        initLocationProcedure();
    });
</script>
<div id="map" style="height:400px;width:100%;margin:0;padding:0;"></div>

Сформируйте ссылку в формате: geo:ШИРОТА,ДОЛГОТА?z=МАСШТАБ, например:
Посмотреть на карте - откройте с мобильного или с устройства с поддержкой GEO-ссылок.

<a href="geo:47.2332,39.715?z=18">Посмотреть на карте</a>

Чтобы открыть карту Яндекса с передачей местоположения используйте следующую ссылку:
https://yandex.ru/maps/?ll=ДОЛГОТА,ШИРОТА&z=МАСШТАБ, обратите внимание, у яндекса координаты передаются в обратной последовательности!
Посмотреть на карте Яндекса

<a href="https://yandex.ru/maps/?ll=39.715,47.2332&z=19">Посмотреть на карте Яндекса</a>

Чтобы открыть карту Google с передачей местоположения используйте следующую ссылку:
https:///www.google.com/maps?q=ШИРОТА,ДОЛГОТА Посмотреть на карте Googleили
https://maps.google.com/maps?daddr=ШИРОТА,ДОЛГОТА Посмотреть на карте Google

Чтобы открыть карту Apple с передачей местоположения используйте следующую ссылку:
https:///maps.apple.com/?ll=ШИРОТА,ДОЛГОТА Посмотреть на карте Apple

Смотрите также:


.