Опрос
Вы участвуете в программе Windows Insider?
Популярные новости
Обсуждаемые новости

15.03.2011 11:39 | dronov_va

Новая версия языка разметки веб-страниц HTML 5 имеет поистине неисчерпаемые возможности. Так, помимо всего прочего, она предоставляет средства для определения местоположения - так называемый Geolocation API. То есть мы можем в своих веб-сценариях определить точное местоположение - широту и долготу - компьютера клиента. Разумеется, для этого компьютер должен иметь соответствующие сенсоры, например, GPS.

Именно о Geolocation API и пойдёт речь в данной статье.


1. Подготовительные действия
Прежде чем использовать Geolocation API в своих веб-сценариях, необходимо ознакомимся с параграфами 2.2 и 3.2 статьи, посвящённой тегам <AUDIO> и <VIDEO>. Описанные там вещи обязан принять во внимание любой веб-программист, который планирует вплотную заняться HTML 5.


2. Объект Geolocation
Любой веб-браузер поддерживает объект Window, представляющий его (браузера) окно или вкладку. Экземпляр этого объекта, представляющий текущее окно или вкладку и созданный самим браузером, можно получить из переменной window, которая доступна в любом веб-сценарии.

var oWindow = window;


Объект Window поддерживает свойство navigator, хранящее экземпляр объекта Navigator, который также создаётся самим веб-браузером. Этот объект представляет саму программу браузера.

var oNavigator = window.navigator;


Объект Navigator, в свою очередь, поддерживает свойство geolocation, хранящее экземпляр объекта Geolocation, который создаётся самим браузером. А вот этот объект уже представляет сведения о местоположении.

var oGeolocation = window.navigator.geolocation;


Значит, чтобы получить сведения о текущем местоположении компьютера, мы должны запросить экземпляр объекта Geolocation из свойства window.navigator.geolocation, как и было показано в предыдущем примере.

Примечание:
Свойство geolocation поддерживается только теми браузерами, которые поддерживают HTML 5.

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

Примечание:
При любой попытке получить данные о местоположении из веб-сценария браузер выводит посетителю запрос, предоставлять ли сайту, которому принадлежит веб-страница, доступ к этим данным или нет. Internet Explorer 9 RC в этом случае предоставляет единственный выбор - "Разрешить однократно". Данные о местоположении будут успешно получены веб-сценарием только в том случае, если посетитель ответит на этот запрос положительно.


3. Однократное получение сведений о местоположении
Проще всего получить сведения о местоположении однократно, в текущий момент времени. Сейчас мы выясним, как это делается.

3.1. Метод getCurrentPosition объекта Geolocation
Для однократного получения данных о местоположении применяется метод getCurrentPosition объекта Geolocation. Формат его вызова приведён ниже.

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

ет вызвана в случае возникновения
ошибки при определении местоположения>[,
<дополнительные параметры>]]
);[/code]
Рассмотрим параметры этого метода. Они заслуживают весьма длинного и обстоятельного разговора.

Прежде всего, метод getCurentPosition не выполняет собственно получение местоположения. Он только запускает процесс его получения, после чего немедленно завершает свою работу. Дело в том, что получение местоположения может выполняться довольно долго, и когда именно этот процесс завершится, никто не предсказать не может. А останавливать работу веб-сценария на всё время, пока местоположение будет определяться, - очень плохой стиль программирования.

3.2. Собственно получение местоположения
Как только местоположение будет успешно определено, выполнится <функция>, переданная методу getCurrentPosition в качестве первого параметра (см. выше описание формата вызова данного метода). Это может быть либо имя именованной функции, либо объявление анонимной функции. Кстати, это единственный обязательный параметр данного метода.

[code]function showPosition(p)
{
. . .
}

. . .

window.navigator.geolocation.getCurrentPosition(showPosition);[/code]
Здесь мы объявили обычную именованную функцию showPosition, которая выведет сведения о местоположении на веб-страницу, и указали её имя в вызове метода getCurrentPosition.

[code]window.navigator.geolocation.getCurrentPosition(
function (p)
{
. . .
});[/code]
А здесь мы указали анонимную функцию прямо в вызове метода getCurrentPosition.

Функция, которая будет вызываться при успешном получении местоположения, должна принимать один параметр (см. примеры выше - там он присутствует под именем p). Этим параметром в функцию будет передан экземпляр объекта Position, содержащий сведения о собственно местоположении.

Объект Position поддерживает два свойства, перечисленные ниже. Оба этих свойства доступны только для чтения.

  • coords - возвращает сами сведения о местоположении в виде экземпляра объекта Coordinates (подробнее этот объект мы рассмотрим чуть позже).
  • timestamp - возвращает значение времени, в которое было получено данное местоположение. Это значение представляет собой количество миллисекунд, прошедших с полуночи 1 января 1970 года, в виде целого числа. Это, кстати, обычный "компьютерный" формат представления времени.


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

  • accuracy - возвращает точность определения широты и долготы в метрах в виде целого числа.
  • altitude - возвращает высоту в метрах в виде целого числа. Если высота не может быть определена, возвращается значение null.
  • altitudeAccuracy - возвращает точность определения высоты в метрах в виде целого числа. Если эта величина не может быть определена, возвращается значение null.
  • latitude - возвращает широту в градусах в виде целого числа от -90 до 90.
  • longitude - возвращает долготу в градусах в виде целого числа от -180 до 180.


На заметку
Спецификации HTML 5 также определяют свойства heading и speed объекта Coordinates, возвращающие, соответственно, направление движения в градусах и скорость движения в м/с. Однако в Internet Explorer 9 данные свойства пока не поддерживаются; возможно, их поддержка появится в будущих версиях браузера.

[code]function (p)
{
var iLatitude = p.coords.latitude;
var iLongitude = p.coords.longitude;
if (p.coords.altitude)
var iAltitude = p.coords.altitude
else
var iAltitude = 0;
}[/code]
Здесь мы сначала получаем значения широты и долготы и помещаем их в переменные. Далее мы проверяем, доступно ли значение высоты, для чего используем обычный подход, применяемый всеми JavaScript-программистами, - особое условное выражение. В качестве условия в этом выражении мы подставили свойство altitude. Если оно содержит числовую величину (то есть значение высоты доступно), эта величина будет преобразована в значение true, условие станет истинным, и выполнится выражение, помещающее значение высоты в переменную. Если же оно содержит значение null (значение высоты недоступно), это значение будет преобразовано в false, условие станет ложным, и выполнится выражение, помещающее в переменную значение 0 (своего рода высота по умолчанию).

3.3. Обработка ошибок
Но может случиться и так, что при попытке получения местоположения возникнет ошибка. Это может произойти из-за того, что компьютер не имеет средств для определения местоположения (а большинство современных настольных компьютеров их и не имеет) или они не работают должным образом. Как быть в таком случае?

Именно поэтому метод getCurrentPosition объекта Geolocation поддерживает второй параметр, являющийся необязательным. Им передаётся функция, которая будет вызвана при возникновении ошибки.

[code]window.navigator.geolocation.getCurrentPosition(
function (p)
{
. . .
},
function (err)
{
. . .
});[/code]
Здесь мы указали вторым параметром метода getCurrentPosition анонимную функцию.

Функция, выполняющаяся при возникновении ошибки, должна принимать один параметр (в примере выше он присутствует под именем err). Этим параметром в функцию будет передан экземпляр объекта PositionError, хранящий сведения о возникшей ошибке.

Объект PositionError поддерживает два свойства, которые описаны ниже. Оба этих свойства доступны только для чтения.

  • code - возвращает код ошибки в виде целого числа.
  • message - возвращает текстовое описание ошибки в виде строки.


Кроме того, объект PositionError поддерживает три свойства, хранящих коды трёх самых часто возникающих ошибок и также доступных только для чтения.

  • PERMISSION_DENIED - посетитель запретил данному веб-сайту получать информацию о местоположении (числовое значение - 1).
  • POSITION_UNAVAILABLE - не удаётся получить данные о местоположении (числовое значение - 2).
  • TIMEOUT - промежуток времени (таймаут), в течении которого должны быть получены данные о местоположении, истёк, а сами данные так и не были получены (числовое значение - 3).



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

[code]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;
}

. . .
}[/code]
На взгляд автора, в веб-сценариях, обращающихся к сведениям о местоположении, следует всегда предусматривать средства по обработке ошибок, которые могут возникнуть при этом. В самом деле, компьютер может быть не оснащён средствами по установлению местоположения, они могут не работать как положено, они могут быть отключены, кроме того, посетитель может запретить к ним доступ. Нам придётся как-то обрабатывать все эти ситуации, иначе наши веб-сценарии будут выдавать ошибки или не функционировать должным образом.

3.4. Указание дополнительных параметров
Кроме того, при вызове метода getCurrentPosition объекта Geolocation мы можем указать дополнительные параметры, влияющие на процесс получения данных о местоположении. Таких параметров немного, но в некоторых ситуациях они могут помочь.

Дополнительные параметры передаются методу getCurrentPosition третьим, также необязательным, параметром. Они должны представлять собой экземпляр объекта Object (базового объекта JavaScript), содержащий определённые свойства, которые и представляют эти параметры. Таких свойств (и соответствующих им дополнительных параметров) три.

  • enableHighAccuracy. Значение true указывает браузеру попытаться получить как можно более точное значение данных о местоположении (широты, долготы и высоты); при этом, однако, процесс получения данных может потребовать больше времени, а энергопотребление компьютера может возрасти. Значение false этого параметра затребует у браузера обычные данные о местоположении, которые могут оказаться не очень точными. Значение по умолчанию - false.

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

    Значение этого таймаута указывается в виде целого числа в миллисекундах. Если указать значение 0 или отрицательное значение, система вообще не будет кэшировать данные о местоположении, а станет при каждом запросе получать их заново. Если же указать значение Infinity, данные о местоположении будут храниться в кэше всегда, и именно они будут возвращаться при запросе (непонятно только, зачем это нужно). Значение по умолчанию - 0 (то есть кэширование отключено).


[code]window.navigator.geolocation.getCurrentPosition(
function (p)
{
. . .
},
function (err)
{
. . .
},
{
enableHighAccuracy: true,
timeout: 60000,
maximumAge: 600000
});[/code]
Здесь мы затребовали точные данные о местонахождении, установили таймаут их получения в одну минуту (60000 миллисекунд), а таймаут их кэширования - в 10 минут (600000 миллисекунд).

3.5. Пример веб-страницы, выводящей сведения о местоположении
Ниже приведён HTML-код страницы, единомоментно запрашивающей у системы сведения о местоположении и выводящей их на экран.

[code]<!DOCTYPE html>
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<TITLE>Определение местоположения</TITLE>
</HEAD>
<BODY>
<P ID="pLat"></P>
<P ID="pLong"></P>
<P ID="pAlt"></P>
<P ID="pError"></P>
<SCRIPT>
window.navigator.geolocation.getCurrentPosition(
function (p)
{
var oPLat = document.getElementById("pLat");
var oPLong = document.getElementById("pLong");
var oPAlt = document.getElementById("pAlt");
oPLat.innerHTML = p.coords.latitude;
oPLong.innerHTML = p.coords.longitude;
oPAlt.innerHTML = p.coords.altitude;
},
function (err)
{
var oPError = document.getElementById("pError");
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;
}
oPError.innerHTML = mess;
});
</SCRIPT>
</BODY>
</HTML>[/code]
В принципе, здесь всё понятно без особых пояснений.

Cвойство innerHTML поддерживается всеми объектами - элементами веб-страницами, способными иметь содержимое, и хранит строку с HTML-кодом, создающим это самое содержимое. Мы можем присвоить этому свойству строку с HTML-кодом, создающим новое содержимое элемента веб-страницы, - и этот элемент получит новое содержимое. В нашем примере мы используем свойство innerHTML, чтобы вывести в соответствующих абзацах широту, долготу, высоту и описание возникшей ошибки.


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

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

[code]<местоположение>.watchPosition(
<функция, которая будет вызвана каждый раз в случае успешного
определения местоположения>[,
<функция, которая будет вызвана каждый раз в случае
возникновения ошибки при определении местоположения>[,
<дополнительные параметры>]]
);[/code]
Как видим, этот метод принимает те же параметры, что и знакомый нам по параграфу 3 метод getCurrentPosition.

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

[code]var iIdent = window.navigator.geolocation.watchPosition(
function (p)
{
. . .
},
function (err)
{
. . .
});[/code]
При первом вызове метода watchPosition сразу же запустится операция по получению текущего местоположения. Если она увенчается успехом, будет вызвана функция, переданная данному методу первым параметром, в противном случае - функция, переданная вторым параметром. Как видим, всё то же самое, что и в случае метода getCurrentPosition.

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

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

[code]window.navigator.geolocation.clearWatch(iIdent);[/code]
Ниже приведён HTML-код веб-страницы с двумя кнопками, имеющими "говорящие" надписи Подписаться и Отписаться. Первая кнопка выполняет "подписку" на получение данных о местоположении, а вторая её отменяет.

[code]<!DOCTYPE html>
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<TITLE>Определение местоположения</TITLE>
</HEAD>
<BODY>
<P ID="pLat"></P>
<P ID="pLong"></P>
<P ID="pAlt"></P>
<P ID="pError"></P>
<FORM>
<INPUT TYPE="button" ID="btnWatch" VALUE="Подписаться">
<INPUT TYPE="button" ID="btnClear" VALUE="Отписаться" DISABLED>
</FORM>
<SCRIPT>
var oBtnWatch = document.getElementById("btnWatch");
var oBtnClear = document.getElementById("btnClear");

var iIdent;

oBtnWatch.addEventListener("click",
function()
{
iIdent = window.navigator.geolocation.watchPosition(
function (p)
{
var oPLat = document.getElementById("pLat");
var oPLong = document.getElementById("pLong");
var oPAlt = document.getElementById("pAlt");
oPLat.innerHTML = p.coords.latitude;
oPLong.innerHTML = p.coords.longitude;
oPAlt.innerHTML = p.coords.altitude;
},
function (err)
{
var oPError = document.getElementById("pError");
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;
}
oPError.innerHTML = mess;
});
oBtnWatch.disabled = true;
oBtnClear.disabled = false;
}, false);

oBtnClear.addEventListener("click",
function()
{
window.navigator.geolocation.clearWatch(iIdent);
oBtnWatch.disabled = false;
oBtnClear.disabled = true;
}, false);
</SCRIPT>
</BODY>
</HTML>[/code]
Кнопку Отписаться мы сделали изначально недоступной, для чего вставили в создающий её тег <INPUT> атрибут DISABLED. Это сделано, чтобы посетитель не смог случайно отменить "подписку", которую ещё не выполнил.

К событию click кнопки Подписаться мы привязываем обработчик, который выполняет "подписку" на получение данных о местоположении. (Событие click возникает в элементе веб-страницы при щелчке на нём.) Код, выполняющий получение этих данных, вывод их на экран и обработку ошибок, мы позаимствовали из веб-страницы, рассмотренной в параграфе 3.5.

Кроме того, обработчик события click кнопки Подписаться делает эту кнопку недоступной, а кнопку Отписаться, наоборот, доступной. За доступность элемента управления, и кнопки в том числе, для посетителя "отвечает" свойство disabled; значение false этого свойства делает элемент управления доступным, а значение true - недоступным. Это нужно, чтобы посетитель не смог выполнить "подписку" повторно, но, вместе с тем, смог от неё отказаться.

А обработчик события click кнопки Отписаться занимается тем, что отменяет сделанную ранее "подписку", делает кнопку Отписаться недоступной, а кнопку Подписаться - доступной. Фактически он возвращает веб-страницу в изначальное состояние.


5. Что делать, если браузер не поддерживает Geolocation API
Действительно, ведь не все браузеры, присутствующие в настоящий момент на рынке, поддерживают Geolocation API, и вообще HTML 5. И если мы откроем любую из созданных нами веб-страниц в таком браузере, то получим ошибку выполнения веб-сценария.

Для проверки, поддерживает ли браузер Geolocation API, мы можем использовать подход, описанный в параграфе 3.2 (пример, где мы проверяли, доступно ли значение высоты).

[code]if (window.navigator.geolocation) {
//Geolocation API поддерживается

window.navigator.geolocation.getCurrentPosition(
function (p)
{
. . .
},
function (err)
{
. . .
});
} else {
//Geolocation API не поддерживается
}[/code]
Если браузер поддерживает Geolocation API, то свойство geolocation экземпляра объекта Navigator будет содержать экземпляр объекта Geolocation. Если его использовать в качестве условия в условном выражении, оно будет преобразовано в значение true, и условие станет истинным. В результате выполнится секция if условного выражения, где находится код, выполняющий запрос данных о местоположении (или "подписку" на получение этих данных, или отмену этой "подписки").

Если же браузер не поддерживает Geolocation API, то свойство geolocation экземпляра объекта Navigator будет содержать значение undefined (то есть данного свойства вообще нет). Будучи использованным в качестве условия в условном выражении, это значение будет преобразовано в false, и условие станет ложным. Тогда выполнится секция else условного выражения, где мы можем поместить код, предупреждающий посетителя о недоступности данных о местоположении или делающий что-то ещё.


Дополнительные материалы



dronov_va, TheVista.Ru Team
Март 2011

Комментарии

Комментариев нет...
Для возможности комментировать войдите в 1 клик через

По теме

Акции MSFT
420.55 0.00
Акции торгуются с 17:30 до 00:00 по Москве
Все права принадлежат © ms insider @thevista.ru, 2022
Сайт является источником уникальной информации о семействе операционных систем Windows и других продуктах Microsoft. Перепечатка материалов возможна только с разрешения редакции.
Работает на WMS 2.34 (Страница создана за 0.052 секунд (Общее время SQL: 0.03 секунд - SQL запросов: 53 - Среднее время SQL: 0.00057 секунд))
Top.Mail.Ru