Você está aqui: Home ‣ Dive Into HTML5 ‣
❧
eolocalização é a arte de descobrir aonde você está no mundo e (opcionalmente) compartilhar essa informação com as pessoas que você confia. Há mais de uma maneira de descobrir aonde você está — seu endereço IP, sua conexão de rede sem fio, com que torre de celular seu telefone está falando, ou hardware GPS dedicado que calcula latitude e longitude da informação enviada por satélites no céu.
☞P: Geolocalização parece assustador. Posso desligá-la?
R: Privacidade é uma preocupação óbvia quando se está falando sobre compartilhar sua localização física com um servidor web remoto. A API de geolocalização diz explicitamente: “User Agents não devem enviar informação de localização para sites na Web sem a expressa permissão do usuário.” Em outras palavras, compartilhar a sua localização é sempre opcional. Se você não quiser, você não tem que fazê-lo.
❧
A API de geolocalização permite que você compartilhe sua localização em sites confiáveis. A latitude e longitude são disponibilizadas na página via JavaScript, que por sua vez pode ser enviado a um servidor web e fazer coisas como encontrar locais ao seu redor ou mostrar sua posição em um mapa.
Como você pode ver na tabela a seguir, a API de geolocalização é suportada pela maioria dos navegadores desktop e dispositivos móveis. Além disso, vários navegadores e dispositivos antigos podem oferecer suporte via bibliotecas de terceiros, como veremos depois neste capítulo.
IE | Firefox | Safari | Chrome | Opera | iPhone | Android |
---|---|---|---|---|---|---|
9.0+ | 3.5+ | 5.0+ | 5.0+ | 10.6+ | 3.0+ | 2.0+ |
Junto com o suporte padrão da API de geolocalização, há tambem várias APIs de dispositivos específicos em outras plataformas móveis. Falarei sobre tudo isso ainda neste capítulo.
❧
A API de geolocalização centraliza tudo em volta da sua nova
propriedade global chamada navigator
com o objeto:
navigator.geolocation
.
O simples uso da API de geolocalização se parece com isso:
function get_location() {
navigator.geolocation.getCurrentPosition(show_map);
}
Porém isso não detecta o posicionamento (latitude e longitude), não há tratamento de erros e não retorna opções. Você pode incluir uma verificação para detectar se há suporte para a API de geolocalização. Para detectar se há suporte, você pode usar o Modernizr:
function get_location() {
if (Modernizr.geolocation) {
navigator.geolocation.getCurrentPosition(show_map);
} else {
// no native support; maybe try Gears?
}
}
⇜ EU POSSO TER GEOLOCALIZAÇÃO?
O que você faz sem o suporte da geolocalização é contigo. Eu explicarei
como fazer um fallback em um minuto, mas antes eu quero falar sobre o que
acontecerá durante a chamada do método
getCurrentPosition()
. Como
eu mencionei no começo deste capítulo, o suporte
da geolocalização é opcional. Isso significa que seu browser
nunca irá forçar você revelar sua localização física atual para um
servidor remoto. A experiência do usuário é diferente de browser pra
browser. No Mozilla Firefox, a chamada do método
getCurrentPosition()
da API de geolocalização
fará com que o browser mostre uma “barra de notificação” no topo da janela
do navegador. Essa barra se parece com isso:
Há muita coisa acontecendo aqui. Você, como um usuário final,
Além disso, essa barra é
Você acabou de ver o código em JavaScript com que fez essa barra de
notificação aparecer. É uma chamada de função única que tem uma função de
callback (no qual chamei de show_map
). A chamada do método
getCurrentPosition()
retornará a localização imediatamente,
mas isso não quer dizer que você terá a localização do usuário. O primeiro
lugar que é garantido para você o acesso a localização do usuário é na
função de callback. A função de callback se parece com isso:
function show_map(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
// let's show a map or do something interesting!
}
A função de callback será chamada com um único parâmetro, e retornará um
objeto com duas propriedades: coords
e
timestamp
. O timestamp é somente a data e o horário de quando
a localização foi calculada. (Uma vez que tudo isso está acontecendo de
forma assíncrona, você poderá realmente não saber quando irá acontecer com
antecedência. Pode demorar algum tempo para que o usuário visualize a
barra de notificação e aceite compartilhar sua localização. Dispositivos
com GPS dedicado podem demorar mais tempo para se conectar
com o satélite do GPS. E assim por diante.) O objeto
coords
possui propriedades como latitude
e
longitude
que são exatamente o que parece ser: a localização
física do usuário no mundo.
Propriedade | Tipo | Observação |
---|---|---|
coords.latitude |
double | graus decimais |
coords.longitude |
double | graus decimais |
coords.altitude |
double ou null |
metros em elipsoide de referência |
coords.accuracy |
double | metros |
coords.altitudeAccuracy |
double ou null |
metros |
coords.heading |
double ou null |
graus em sentido do norte verdadeiro |
coords.speed |
double ou null |
metros/segundos |
timestamp |
DOMTimeStamp | como um objeto de Date() |
Somente três de uma das propriedades são garantidas
(coords.latitude
, coords.longitude
, e
coords.accuracy
). O restante pode voltar null
,
dependendo da capacidade do seu dispositivo e a distância que o servidor
está de você. As propriedades heading
e
speed
serão calculadas baseadas na posição anterior do
usuário, se possível.
❧
Geolocalização é complicado. Coisas podem dar errado. Eu havia dito que o
“consentimento do usuário” é estranho. Se sua aplicação precisa da
localização do usuário mas o usuário não permitir, você está ferrado. O
usuário sempre ganha. Se ele não permitir, o que apareceria como mensagem?
Veja o segundo parâmetro do método getCurrentPosition()
: um
erro é chamado na função de callback.
navigator.geolocation.getCurrentPosition(
show_map, handle_error)
Se qualquer coisa sair errado, sua função callback de erro será chamada
com um objeto PositionError
.
Propriedade | Tipo | Observações |
---|---|---|
code |
short | um valor enumerado |
message |
DOMString | não usado para usuários finais |
A propriedade code
retornará um desses resultados
PERMISSION_DENIED
(1
) se o usuário clicar em
“não compartilhar” ou qualquer outra coisa que bloqueará seu acesso e
sua localização.
POSITION_UNAVAILABLE
(2
) se a rede cair ou a
posição do satélite não poder ser resgatada.
TIMEOUT
(3
) se a rede não cair mas o tempo
para calcular a posição do usuário for longo demais. Como saber o que é
“longo demais”? Vou mostrar como definir isso numa próxima seção.
↶ Seja educado na derrota
function handle_error(err) {
if (err.code == 1) {
// user said no!
}
}
☞P: A API de geolocalização pega na Estação Espacial Internacional, na Lua, ou em outros planetas?
R: Os estados específicos da geolocalização, “O sistema de referência geográfica de coordenadas usado pelos atributos é referente ao World Geodetic System (2d) [WGS84]. Nenhum outro sistema de referência é suportado.” A Estação Espacial Internacional está em órbita na Terra, então os astronautas na estacão podem dizer suas localizações por latitude, longitude e altitude. No entanto, o World Geodetic System é centralizado somente na Terra, por isso não podemos usar para saber localizações na Lua ou em outros planetas.
❧
Alguns aparelhos — como iPhone e Android — suportam dois métodos para mostrar sua localização. O primeiro método triangula a sua posição baseando-se na sua localização relativa das diferentes torres da sua operadora de celular. Este método é rápido e não necessita de qualquer hardware de GPS dedicado, mas ele só pega uma ideia aproximada de onde você está.
O segundo método atualmente usa algum hardware de GPS dedicado em seu aparelho para se comunicar com algum satélite de GPS dedicado que está orbitando na Terra. O GPS normalmente pode identificar a sua localização a poucos metros. O lado negativo de um chip de GPS dedicado em seu aparelho é que consome muita energia, então telefones e outros dispositivos geralmente desligam esse chip quando precisa. Isso significa que terá um atraso quando o chip for inicializado para se conectar com o satélite. Se você sempre usa o Google Maps em um iPhone ou outro smartphone, você já viu os dois métodos em ação. Primeiro você vê um grande círculo que aproxima sua posição (procurando uma torre de celular próxima), então um círculo menor (triangulando com outras torres de celulares), então um único ponto com sua posição exata (pego por um satélite de GPS).
A razão de eu falar isso é que, dependendo da sua aplicação web, você talvez não terá uma grande precisão. Se você estiver somente procurando por alguns cinemas nas proximidades, uma precisão menor provavelmente será o suficiente pra você. Não há muitas salas de cinema, mesmo em cidades maiores, e você provavelmente vai listar mais de uma. Por outro lado, se voce está querendo direções em tempo real, você realmente terá que saber onde o usuário está exatamente para poder dizer “vire à direita em 20 metros” ou qualquer outra coisa.
O método getCurrentPosition()
tem como um terceiro argumento
opcional,
um objeto PositionOptions
. Existem três propriedades que você pode definir no objeto
PositionOptions
. Todas as propriedades são opcionais. Você
pode definir qualquer uma ou todas, ou nenhuma delas.
Propriedade | Tipo | Padrão | Observações |
---|---|---|---|
enableHighAccuracy |
Booleano | false | true pode ser mais lento |
timeout |
long | (sem padrão) | em millisegundos |
maximumAge |
long | 0 | em millisegundos |
A propriedade enableHighAccuracy
é exatamente o que se
parece. Se for verdadeiro, e o dispositivo tiver suporte para tal, e o
usuário permitir compartilhar sua posição, então o dispositivo irá tentar
fornecer uma precisão maior. Tanto iPhones quanto Androids tem uma
permissão separada para baixa e alta precisão, por isso, é possível que a
chamada getCurrentPosition()
com
enableHighAccuracy:true
possa falhar, mas chamar com
enableHighAccuracy:false
poderá dar certo.
A propriedade timeout
é um número em millisegundos que sua
aplicação irá esperar pela posição. Este tempo não será contado
antes do usuário dar permissão para tentar calcular sua posição.
Não é o tempo do usuário; é o tempo da rede.
A propriedade maximumAge
permite que os dispositivos
respondam imediatamente com uma posição em cache. Por exemplo, vamos
chamar o método getCurrentPosition()
por um período, o
usuário permitiu, e a função de callback chamou a posição que foi
calculada exatamente às 10:00 horas da manhã, você chamou o método
getCurrentPosition()
novamente com a propriedade
maximumAge
em 75000
.
navigator.geolocation.getCurrentPosition(
success_callback, error_callback, {maximumAge: 75000});
O que você está dizendo é que você não precisa necessariamente da posição
atual do usuário. Você provavelmente ficará satisfeito sabendo onde ele
esteve em 75 segundos atrás (75000 millisegundos). O dispositivo sabe onde
o usuário foi em 60 segundos atrás (60000 millisegundos), porque sua
posição foi calculada antes da primeira chamada do método
getCurrentPosition()
. Então o dispositivo não precisa
recalcular o localização do usuário novamente. Ele somente retorna
exatamente a mesma informação que foi retornada na primeira chamada: mesma
latitude, mesma longitude, mesma precisão, e mesmo timestamp (10:00 da
manhã).
Antes que você pergunte pela localização do usuário, deve-se pensar sobre
o quanto de precisão você precisa, e definir
enableHighAccuracy
de acordo. Se você precisa encontrar sua
localização mais de uma vez, você deve pensar sobre como uma informação
antiga pode vir ser útil, e definir maximumAge
de acordo. Se
você precisa encontrar sua localização continuamente, então o
método getCurrentPosition()
não é pra você. Você precisa
utilizar o método watchPosition()
.
O método watchPosition()
tem a mesma estrutura que o método
getCurrentPosition()
. Tem duas funcões de callback, uma
necessária para sucesso e uma opcional para qualquer erro que possa dar, e
também pode ter um objeto opcional PositionOptions
que terá
todas as mesmas propriedades que você aprendeu. A diferença é que sua
função de callback irá ser chamada
toda vez que a localização do usuário mudar. Não há necessidade
de pesquisar sua posição toda hora. O dispositivo irá determinar o melhor
intervalo pra pesquisa da localização, e ele irá chamar sua função de
callback sempre que a posição do usuário alterar. Você pode usar isto para
atualizar um marcador em um mapa, fornecendo instruções sobre onde deve
ir, ou o que quiser.
O método watchPosition()
retornará sempre um número. Você
provavelmente deve guardar este número em algum lugar. Se você quiser
parar de ver a mudança de localização do usuário, você pode chamar o
método clearWatch()
e passar este número, e o dispositivo irá
parar de chamar a funcão de callback. Isso funciona de forma parecida com
as funções Javascript setInterval()
e
clearInterval()
.
❧
Antes da versão 9 (tecnicamente 9.0RC1), o Internet Explorer não tem suporte para a API de geolocalização da W3C. Mas não se desespere! Gears é um plugin de código aberto da Google que funciona em Windows, Mac, Linux, Windows Mobile, e Android, que fornece recursos para os navegadores antigos. Um desses recursos que o Gears fornece é a API de geolocalização. Ele não é bem a API de geolocalização da W3C, mas tem o mesmo resultado.
Enquanto estamos em um assunto de plataformas legadas, gostaria de deixar bem claro que as plataformas antigas tem suas próprias APIs de geoloalização. BlackBerry, Nokia, Palm, e OMTP BONDI todas fornecem suas próprias APIs. É claro, todas elas trabalham de forma diferente do Gears, que por sua vez funciona de forma diferente da API de geolocalização da W3C. Wheeeeee!
❧
geo.js
é uma biblioteca JavaScript, de código aberto, com licença
MIT que facilita o uso entre as diferentes
APIs de geolocalização da W3C, a Gears
API, e as APIs fornecidas pela próprias
plataformas. Para usá-la, você irá precisar adicionar dois scripts no
rodapé da sua página. (Tecnicamente, você poderia colocar eles em qualquer
lugar, mas scripts no <head>
vão fazer com que sua
página carregue mais devagar. Então, não faça isso!)
O primeiro script é o
gears_init.js
, que inicializará o Gears caso estiver instalado. O segundo script é o
geo.js
.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dive Into HTML5</title>
</head>
<body>
...
<script src="gears_init.js"></script>
<script src="geo.js"></script>
</body>
</html>
⇜ Não deixe isso no seu <head>
Agora você está pronto para usar qualquer API de geolocalização.
if (geo_position_js.init()) {
geo_position_js.getCurrentPosition(geo_success, geo_error);
}
Vamos começar devagar. Primeiro, você precisa chamar o método
init()
. O método init()
retorna
true
se o suporte para a API de geolocalização
estiver disponível.
if (geo_position_js.init()) {
Chamando o método init()
ele não irá buscar sua localização.
Ele somente verifica que é possível procurar sua localização. Para
encontrar sua localização, você precisa chamar o método
getCurrentPosition()
.
geo_position_js.getCurrentPosition(geo_success, geo_error);
O método getCurrentPosition()
irá fazer seu navegador pedir
sua permissão para encontrar e compartilhar sua localização. Se sua
geolocalização está sendo fornecida pelo Gears, irá aparecer uma janela
perguntando se você permite o Gears utilizar alguns dados. Se seu
navegador tem suporte nativo para geolocalização, a janela que irá
aparecer, é diferente. Por exemplo, o Firefox 3.5 tem suporte nativo para
geolocalização. Se você tentar procurar sua localização no Firefox 3.5,
aparecerá uma barra de notificação no topo da página perguntando se você
quer compartilhar sua localização com este site.
O método getCurrentPosition()
passa dois parâmetros, ambos
funções. Se o método getCurrentPosition()
conseguiu encontrar
sua localização — isto é, se você deu permissão, a API de
geolocalização irá funcionar como mágica — a função passada no primeiro
parâmetro será chamada. Neste exemplo, a função de callback de sucesso é
chamada de geo_success
.
geo_position_js.getCurrentPosition(geo_success, geo_error);
A função de callback tem um único parâmetro, e que contém a posição do usuário.
↶ Chamada de sucesso
function geo_success(p) {
alert("Encontrado na latitude " + p.coords.latitude +
", longitude " + p.coords.longitude);
}
Se o método getCurrentPosition()
não encontrar sua
localização — porque você não deu permissão, ou a API de
geolocalização falhou por algum motivo — será chamada a função no segundo
parâmetro. Neste exemplo, o callback de falha é chamado de
geo_error
.
geo_position_js.getCurrentPosition(geo_success, geo_error);
O callback de falha não tem parâmetros
↶ Chamada de erro
function geo_error() {
alert("Não conseguimos encontrar você!");
}
geo.js
não tem suporte para o método
watchPosition()
. Se você precisar da localização contínua,
irá precisar ativar o método getCurrentPosition()
você mesmo.
❧
Aqui está um exemplo real usando a
geo.js
para tentar pegar sua
localização e mostrar um mapa de onde você está quase que
instantaneamente:
Seu navegador suporta geolocation.
Clicar para ver sua localização.
Como isso funciona? Vamos dar uma olhada. No carregamento da página, esta
página chama geo_position_js.init()
para determinar se a
geolocalização está disponível em qualquer uma das interfaces que
geo.js
suporta. Se tiver suporte, ele cria um link que você
pode clicar para ver sua localização. Clicando no link é chamado então o
método lookup_location()
, aqui está:
function lookup_location() {
geo_position_js.getCurrentPosition(show_map, show_map_error);
}
Se você permitir rastrear sua localização, e o serviço de backend
conseguir determinar sua localização, geo.js
chama a primeira
função de callback, show_map()
, com um único parâmetro,
loc
. O objeto loc
tem uma propriedade
coords
no qual contém sua latitude, longitude e precisão.
(Este exemplo não usa a precisão.) O resto do método
show_map()
usa a API de mapas do Google Maps
para mostrar um mapa.
function show_map(loc) {
$("#geo-wrapper").css({'width':'320px','height':'350px'});
var map = new GMap2(document.getElementById("geo-wrapper"));
var center = new GLatLng(loc.coords.latitude, loc.coords.longitude);
map.setCenter(center, 14);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.addOverlay(new GMarker(center, {draggable: false, title: "Você está aqui (mais ou menos)"}));
}
Se geo.js
não conseguir determinar sua localização, ele
chamará o segundo callback, show_map_error()
.
function show_map_error() {
$("#live-geolocation").html('Não foi possível determinar sua localização.');
}
❧
❧
Isso foi “Você Está Aqui (Assim Como Todo Mundo Está)” e Outras Palavras Bonitas; Consulte o Sumário, caso queira continuar com a leitura.
Em associação a Google Press, O’Reilly está distribuindo este livro em variados formatos, incluindo papel, ePub, Mobi, DRM-free e PDF. A edição paga é chamada “HTML5: Up & Running” e está disponível agora. Este capítulo está incluído na versão paga.
Se você gostou deste capítulo e quer mostrar sua apreciação, basta comprar o livro “HTML5: Up & Running” com esse link afiliado ou comprar a edição eletrônica diretamente da O’Reilly. Você vai ganhar um livro, e eu vou ganhar um trocado. Atualmente, não aceito doações diretas.
Copyright MMIX–MMXI Mark Pilgrim