Статьи

Приложения HTML5: позиционирование с помощью геолокации

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

Три года назад у смартфона «бум» был еще неопределенной возможностью. Сегодня нас окружает общество наркоманов смартфонов, которые живут так, как будто их жизнь не может продолжаться без мгновенного мобильного доступа к сети, электронной почте и приложениям на все случаи жизни. Мобильные устройства прошли долгий путь всего за три коротких года и теперь поддерживают широкий спектр полезных функций, помимо телефонных звонков. Для таких людей, как я, геолокация — одно из самых полезных дополнений. Многие устройства iPhone и Android были оснащены оборудованием GPS, которое может генерировать надежные географические данные, и в этой статье мы обсудим геолокационные возможности HTML5. Моя цель — помочь вам воспользоваться преимуществами технологии геолокации в вашем следующем проекте, пройдя по следующим темам:

  • Геолокация браузера и как она работает
  • Как работают асинхронные вызовы функций
  • Как использовать API getCurrentPosition
  • Что в данных геолокации
  • Как использовать геолокацию на основе IP-адресов, когда браузеры не предоставляют встроенную поддержку
  • Как отобразить карту, используя данные геолокации
  • Как использовать API WatchPosition и clearWatch

Чтобы обнаружить местоположение клиентского устройства в прошлом, обычно необходимо проверить IP-адрес клиента и сделать разумное предположение относительно того, где это устройство было расположено. Тем не менее, как часть усилий HTML5, W3C разработал набор API-интерфейсов, чтобы эффективно позволить клиентскому устройству (то есть вашим iPhone 3G +, телефонам Android 2.0+ или даже обычным браузерам настольных компьютеров) получать информацию о географическом положении с помощью JavaScript , Когда мы смотрим на ландшафт веб-браузеров, нативная поддержка геолокации начинает проникать в основные приложения медленными и устойчивыми темпами. Одно существенное приложение, которое использует геолокацию, является Google Maps. На момент написания этой статьи поддержка геолокации полностью доступна только в нескольких браузерах (см. Ниже), но похоже, что большинство современных браузеров используют эту полезную функциональность:

  • Firefox 3.5+: да
  • Chrome 5 бета: Да
  • iPhone Safari: Да
  • Opera 10.5 dev build: Да
  • Сафари: нет
  • Internet Explorer: нет

Для тех, кто заинтересован в чтении спецификаций геолокации W3C, здесь есть ссылка . Один из разделов, о которых стоит здесь упомянуть, — это раздел 6.2.8, озаглавленный: «API геолокации должен быть независим от основных источников информации о местоположении». Это предполагает, что базовая технология на устройстве может достигать геолокации с помощью GPS, триангуляции вышек сотовой связи или, возможно, других методов. API геолокации не будет определять способ определения информации о местоположении. Незнание того, как была достигнута геолокация, обычно не является проблемой, но вы можете заметить, что точность информации о местоположении может сильно различаться в зависимости от используемой техники.

Асинхронная функция — это та, которая выполняется вне основного потока программы. В контексте JavaScript это означает, что наш код будет вызывать функцию и затем продолжать выполнять операторы до ее возврата. Следуя этой модели, наш код должен выглядеть примерно так:

Поскольку ответ на функцию do_something () предоставляется нам асинхронно, мы должны назначить функцию, которая получит ответ и будет использовать его. Поэтому мы должны определить другую функцию handle_response_to_do_something (), которая отображает результат в диалоговом окне.

Теперь вы можете спросить, зачем нам это знать? Ну, потому что, когда наше приложение пытается запросить свое местоположение, пользователь устройства должен согласиться поделиться информацией о своем местоположении с нашим приложением. Если бы это действие не было асинхронным, то все в браузере зависало бы до тех пор, пока пользователь не ответит, и это явно не так, как хотелось бы.

API геолокации html5

Давайте поговорим об API геолокации. Первый API, с которым нам интересно работать, это API getCurrentPosition (). При вызове он должен немедленно вернуться, а затем асинхронно получить новый объект Position. В случае успеха этот метод должен вызвать связанный с ним аргумент successCallback с объектом Position в качестве аргумента. Если попытка не удалась и метод был вызван с ненулевым аргументом errorCallback, этот метод должен вызвать errorCallback с объектом PositionError в качестве аргумента.

Итак, давайте начнем с создания нашей страницы HTML5, которая удобнее и проще, чем настройка страницы XHTML 1.0. Все, с чего нам нужно начать, это:

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
  <body>
    <div>
 
    </div>
  </body>
</html>

В строке 1 мы используем новый DTD <! DOCTYPE html>, чтобы определить его как страницу HTML5. Далее мы разместим на нашей странице кнопку, чтобы пользователи могли инициировать процесс определения своего местоположения.

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
  <body>
    <div>
      <button id=”btnInit” >Find my location</button>
    </div>
  </body>
</html>

Теперь мы свяжем кнопку с JavaScript, чтобы инициировать процесс запроса текущего местоположения. Обратите внимание, что теги скрипта не требуют атрибута типа благодаря новому сахару HTML5.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
  <head>
    <script src=»js/jquery-1.4.2.min.js»></script>
    <script>
        jQuery(window).ready(function(){
            jQuery(«#btnInit»).click(initiate_geolocation);
        });
 
        function initiate_geolocation() {
            navigator.geolocation.getCurrentPosition(handle_geolocation_query);
        }
 
        function handle_geolocation_query(position){
            alert(‘Lat: ‘ + position.coords.latitude + ‘ ‘ +
                  ‘Lon: ‘ + position.coords.longitude);
        }
    </script>
  </head>
  <body>
    <div>
      <button id=»btnInit» >Find my location</button>
    </div>
 
  </body>
</html>

В приведенном выше коде мы должны отметить использование JavaScript-инфраструктуры jQuery, чтобы помочь нам быстро начать работу, иначе нам пришлось бы написать дополнительный код для определения готовности страницы, которая не имеет ничего общего с геолокацией. С первым тегом скрипта мы загружаем инфраструктуру jQuery, а затем сразу же используем его в начале второго тега скрипта, чтобы назначить событие click для кнопки, которую мы определили ранее. Мы также написали функцию initiate_geolocation () для выполнения при нажатии кнопки и функцию handle_geolocation_query (position) для асинхронного получения данных геолокации через аргумент position.

На этом этапе, если вы запустите приведенный выше код в браузере, который поддерживает геолокацию (а именно Firefox 3.5+ и iPhone Safari), вы должны увидеть свои координаты широты и долготы. Это работает, если пользователь соглашается поделиться информацией о своем местонахождении с веб-сайтом / веб-приложением, но что, если он не знает, что делиться этой информацией? или что, если есть проблема с получением этой информации?

Было бы неплохо получить уведомление о таких проблемах. К счастью, наш код может обнаруживать эти проблемы, определяя другую функцию, которая выполняется только тогда, когда возникает проблема с получением данных геолокации. Итак, давайте посмотрим, как нужно будет изменить наш код для обнаружения проблем:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html>
  <head>
 
    <script src=»js/jquery-1.4.2.min.js»></script>
    <script>
        jQuery(window).ready(function(){
            jQuery(«#btnInit»).click(initiate_geolocation);
        });
 
        function initiate_geolocation() {
            navigator.geolocation.getCurrentPosition(handle_geolocation_query,handle_errors);
        }
 
        function handle_errors(error)
        {
            switch(error.code)
            {
                case error.PERMISSION_DENIED: alert(«user did not share geolocation data»);
                break;
 
                case error.POSITION_UNAVAILABLE: alert(«could not detect current position»);
                break;
 
                case error.TIMEOUT: alert(«retrieving position timed out»);
                break;
 
                default: alert(«unknown error»);
                break;
            }
        }
 
        function handle_geolocation_query(position){
            alert(‘Lat: ‘ + position.coords.latitude +
                  ‘ Lon: ‘ + position.coords.longitude);
        }
    </script>
  </head>
  <body>
    <div>
      <button id=»btnInit» >Find my location</button>
    </div>
  </body>
</html>

В приведенном выше коде мы ввели новую функцию handle_errors, которая принимает аргумент error. Изучив аргумент ошибки, мы можем проверить тип возникшей ошибки. Обычно браузер идентифицирует одну из этих трех ошибок как причину:

  • Пользователь решил не передавать данные о местоположении
  • Устройство не смогло получить данные о местоположении
  • Тайм-аут устройства в ожидании получения данных о местоположении

Если мы проверим то, что мы получили от API геолокации, мы увидим поля координат и отметки времени. Поле timestamp просто обозначает время, когда был создан экземпляр данных геолокации. Атрибут координаты содержит набор географических координат вместе с их соответствующей точностью, а также набор других необязательных атрибутов, таких как высота и скорость. Ниже приводится описание их в соответствии со спецификациями W3C:

  • Атрибуты широты и долготы представляют собой географические координаты, указанные в десятичных градусах.
  • Атрибут precision обозначает уровень точности координат широты и долготы. Он указывается в метрах и должен поддерживаться всеми реализациями.
  • Атрибут altitude обозначает высоту положения, указанную в метрах над эллипсоидом WGS84 . Если реализация не может предоставить информацию о высоте, значение этого атрибута должно быть нулевым.
  • Атрибут altitudeAccuracy указывается в метрах. Если реализация не может предоставить информацию о высоте, значение этого атрибута должно быть нулевым.
  • Атрибут заголовка обозначает направление движения хост-устройства и указывается в градусах, считая по часовой стрелке относительно истинного севера. Если реализация не может предоставить информацию о заголовке, значение этого атрибута должно быть нулевым.
  • Атрибут speed обозначает текущую наземную скорость хост-устройства и указывается в метрах в секунду. Если реализация не может предоставить информацию о скорости, значение этого атрибута должно быть нулевым.

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

Итак, теперь очевидный вопрос — как насчет тех браузеров, которые вообще не поддерживают геолокацию? Ответ заключается в том, что мы должны использовать внешний сервис геолокации. Эти службы делают все возможное, чтобы сопоставить IP-адрес устройства с географическим местоположением, используя большие базы данных геолокации. Обычно они делают хорошую работу, но иногда они могут страдать от следующих проблем:

  • IP-адреса могут быть связаны с неправильным местоположением (например, неправильный почтовый индекс, город или пригород в столичном регионе).
  • Адреса могут быть связаны только с очень широкой географической областью (например, большой город или штат). Многие адреса связаны только с городом, а не с адресом улицы или местоположением по широте / долготе.
  • Некоторые адреса не будут отображаться в базе данных и поэтому не могут быть сопоставлены (часто это верно для IP-номеров, которые обычно не используются в Интернете).

Важно помнить, что при использовании внешней службы геолокации точность не так хороша, как у геолокации, присущей устройству, и в некоторых случаях она может быть полностью отключена. Кроме того, такие службы не предоставляют никакой информации относительно высоты, скорости или курса устройства. Независимо от того, когда GPS или триангуляция недоступны, они являются хорошим запасным вариантом.

YQL Geo Library — это специальная и легкая библиотека, которая позволяет вам выполнять геолокацию, используя старые добрые сервисы Yahoo. Эта библиотека может делать другие вещи, которые я оставлю вам для изучения, но сейчас давайте посмотрим, как мы должны изменить наш код, чтобы успешно определять местоположение как в поддерживаемых, так и в не поддерживающих браузерах:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<!DOCTYPE html>
<html>
 
  <head>
  <script src=»js/jquery-1.4.2.min.js»></script>
  <script src=»js/yqlgeo.js»></script>
  <script>
    jQuery(window).ready(function(){
        jQuery(«#btnInit»).click(initiate_geolocation);
    })
 
    function initiate_geolocation() {
        if (navigator.geolocation)
        {
            navigator.geolocation.getCurrentPosition(handle_geolocation_query, handle_errors);
        }
        else
        {
            yqlgeo.get(‘visitor’, normalize_yql_response);
        }
    }
 
    function handle_errors(error)
    {
        switch(error.code)
        {
            case error.PERMISSION_DENIED: alert(«user did not share geolocation data»);
            break;
 
            case error.POSITION_UNAVAILABLE: alert(«could not detect current position»);
            break;
 
            case error.TIMEOUT: alert(«retrieving position timedout»);
            break;
 
            default: alert(«unknown error»);
            break;
        }
    }
 
    function normalize_yql_response(response)
    {
        if (response.error)
        {
            var error = { code : 0 };
            handle_error(error);
            return;
        }
 
        var position = {
            coords :
            {
                latitude: response.place.centroid.latitude,
                longitude: response.place.centroid.longitude
            },
            address :
            {
                city: response.place.locality2.content,
                region: response.place.admin1.content,
                country: response.place.country.content
            }
        };
 
        handle_geolocation_query(position);
    }
 
    function handle_geolocation_query(position){
        alert(‘Lat: ‘ + position.coords.latitude + ‘ ‘ +
              ‘Lon: ‘ + position.coords.longitude);
        }
    </script>
 
  </head>
  <body>
    <div>
      <button id=»btnInit» >Find my location</button>
    </div>
 
  </body>
</html>

Так что нового в приведенном выше коде? Три вещи:

  1. Мы импортируем библиотеку геолокации YQL на страницу
  2. Внутри функции initiate_geolocation () код проверяет, чтобы убедиться, что геолокация изначально поддерживается. Если нет, то используется библиотека геолокации YQL.
  3. Наконец, мы определили функцию normalize_yql_response (response) для преобразования результата библиотеки геолокации YQL в формат вывода, аналогичный спецификациям API геолокации W3C.

До сих пор нам удавалось получить координаты широты и долготы устройства, но когда он теряется в центре большого города, одни только координаты широты и долготы не будут такими уж полезными. Мы должны преобразовать эти координаты в какую-то форму, которая более естественно относится к пользователям, например карту. Давайте отобразим карту текущего местоположения, используя Google Static Map API, как показано в следующем разделе кода:

С помощью jQuery мы изменили функцию handle_geolocation_query (position), чтобы создать элемент изображения и добавить его на страницу. Атрибут src элемента изображения установлен на созданный URI, для которого API статической карты Google будет проверять и генерировать изображение карты.

API геолокационных карт HTML5

Теперь, когда мы знаем, как работает API getCurrentPosition, давайте быстро взглянем на API watchPosition. При вызове он должен немедленно вернуться и затем асинхронно запустить процесс наблюдения, определенный следующим набором шагов:

  1. Получите новый объект Position. В случае успеха вызовите связанный successCallback с объектом Position в качестве аргумента. Если попытка не удалась и метод был вызван с ненулевым аргументом errorCallback, этот метод должен вызвать errorCallback с объектом PositionError в качестве аргумента.
  2. Вызывайте соответствующий обратный вызов с новым объектом Position каждый раз, когда реализация определяет, что позиция хост-устройства изменилась.

Этот метод возвращает целочисленное значение, которое однозначно идентифицирует процесс наблюдения. Когда функция clearWatch () вызывается с этим идентификатором, процесс наблюдения должен прекратить получать любые новые определения местоположения и должен прекратить вызывать любые обратные вызовы.

Другими словами, этот API позволяет нашему коду повторно получать информацию о местоположении при изменении местоположения устройства. Давайте посмотрим на страницу скаффолдинга, с которой нужно начать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html>
  <head>
    <script src=»js/jquery-1.4.2.min.js»></script>
    <script>
 
        jQuery(window).ready(function(){
            jQuery(«#btnInit»).click(initiate_watchlocation);
            jQuery(«#btnStop»).click(stop_watchlocation);
        });
 
        var watchProcess = null;
 
        function initiate_watchlocation() {
        }
 
        function stop_watchlocation() {
        }
 
        function handle_errors(error)
        {
            switch(error.code)
            {
                case error.PERMISSION_DENIED: alert(«user did not share geolocation data»);
                break;
 
                case error.POSITION_UNAVAILABLE: alert(«could not detect current position»);
                break;
 
                case error.TIMEOUT: alert(«retrieving position timedout»);
                break;
 
                default: alert(«unknown error»);
                break;
            }
        }
 
        function handle_geolocation_query(position) {
        }
    </script>
  </head>
  <body>
    <div>
      <button id=»btnInit» >Monitor my location</button>
 
      <button id=»btnStop» >Stop monitoring</button>
    </div>
    <div id=”info”></div>
  </body>
</html>

Как вы видите, код очень похож на код, который мы использовали в разделе «getCurrentPostion API» ранее. Однако есть несколько дополнений.

  1. Сначала мы добавили новую кнопку, чтобы позволить нам остановить процесс наблюдения с помощью функции stop_watchlocation () для обработки его щелчка.
  2. У нас есть переменная watchProcess для отслеживания процесса наблюдения.

Чтобы начать процесс, нам нужно добавить код, который вызывает API watchPosition (), как показано ниже:

1
2
3
4
5
function initiate_watchlocation() {
    if (watchProcess == null) {
        watchProcess = navigator.geolocation.watchPosition(handle_geolocation_query, handle_errors);
    }
}

Чтобы остановить процесс, нам нужно добавить код, который вызывает API clearWatch (), как показано ниже:

1
2
3
4
5
6
7
function stop_watchlocation() {
    if (watchProcess != null)
    {
        navigator.geolocation.clearWatch(watchProcess);
        watchProcess = null;
    }
}

Наконец, мы обрабатываем отображение карты и дополнительных данных (например, положение, точность) следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
function handle_geolocation_query(position) {
    var text = «Latitude: » + position.coords.latitude + «<br/>» +
               «Longitude: » + position.coords.longitude + «<br/>» +
               «Accuracy: » + position.coords.accuracy + «m<br/>» +
               «Time: » + new Date(position.timestamp);
    jQuery(«#info»).html(text);
 
    var image_url = «http://maps.google.com/maps/api/staticmap?sensor=false&center=» + position.coords.latitude + ‘,’ + position.coords.longitude +
                    «&zoom=14&size=300×400&markers=color:blue|label:S|»
 
    jQuery(«#map»).remove();
    jQuery(document.body).append(
        jQuery(document.createElement(«img»)).attr(«src», image_url).attr(‘id’,’map’)
    );
}
HTML5 Геолокация нет данных

Я надеюсь, что этот урок дал вам начало в мире API геолокации. Удачи и постарайтесь, чтобы ваш следующий проект использовал преимущества геолокации!