Use Geolocation API do HTML5 e OpenStreetMaps para um formulário mais amigável

Você certamente já se irritou ao preencher um formulário online gigante, cheio de campos. E você certamente já quis se jogar pela janela se tentou preencher esse formulário num celular. A web mobile tem crescido muito, mas digitar no celular ainda é trabalhoso. Faça de tudo pra limitar a frustração dos seus usuários.

E uma ideia é usufruir dos recursos cada vez mais avançados dos navegadores – tanto mobile quanto Desktop. Nesse artigo, quero explorar a Geolocation API do HTML5 para oferecer ao usuário o preenchimento automático dos seus dados de endereço.

É um recurso a mais, no melhor estilo progressive enhancement, que pode ser usado ao pedir pro usuário criar seu cadastro, preencher um endereço de entrega numa loja virtual, e em muitos outros cenários.

A Geolocation API

O que conseguimos, basicamente, é obter as coordenadas – latitude e longitude – do usuário. A API é simples, através do método getCurrentPosition no objeto navigator.geolocation. Note que obtemos as coordenadas através de um callback assíncrono, já que a obtenção dos dados pode demorar um pouco:

navigator.geolocation.getCurrentPosition(function(posicao) {
   alert(posicao.coords.latitude + ', ' + posicao.coords.longitude); 
});

No código acima, apenas mostramos a latitude e a longitude obtidas em um alert. Teste usando o botão abaixo:

Veja o exemplo no CodePen.

O navegador sempre vai pedir autorização ao usuário antes de liberar a informação de localização, mantendo a privacidade.

A API ainda nos permite outras opções. Podemos passar um callback adicional para rodar em caso de erro e até um terceiro argumento com opções adicionais. É possível definir um timeout de espera, permitir que o navegador dê a última posição em cache ou exigir uma nova posição, e até habilitar um modo de alta precisão que pode demorar mais mas dá um resultado melhor. Podemos também usar o método watchPosition, que nos permite monitorar o deslocamento do usuário pedindo a posição várias vezes (útil para uma app de navegação).

A Geolocation API já é suportada em todos os principais navegadores – incluindo IE9.

Dados geográficos com OpenStreetMaps

A geolocation API só vai nos dar as coordenadas. Para implementarmos a funcionalidade de preencher o formulário, precisamos obter os dados do endereço a partir da latitude e da longitude. Mas esse passo não é tão trivial: é preciso buscar em algum banco de dados geográfico.

Há algumas opções de serviços que fazem o chamado reverse geocoding. O Google Maps é uma opção famosa mas tem uma API paga e um pouco mais complicada. O OpenStreetMaps possui um serviço muito simples e aberto para uso, fácil de se integrar em qualquer página Web via JSONP.

O endereço é simples e recebe as coordenadas como argumento. Por exemplo, com a localização da Caelum SP: (clique para ver a resposta)

http://nominatim.openstreetmap.org/reverse?lat=-23.5880894&lon=-46.6321951

Ainda podemos escolher o formato (JSON, XML) e se queremos um callback (JSONP). Como vamos integrar direto na página Web, vamos usar JSONP e nosso callback chamará preencherDados:

http://nominatim.openstreetmap.org/reverse?lat=-23.5880894&lon=-46.6321951&format=json&json_callback=preencherDados

Misturando tudo para uma boa experiência do usuário

Imagine então um formulário de cadastro que precisa de muitas informações. Além do nome e do email, o endereço completo do usuário. Podemos oferecer a opção de preencher automaticamente o endereço com os dados de geolocalização do usuário.

Começamos pegando as coordenadas do usuário com a Geolocation API e montando a URL dinamicamente:

navigator.geolocation.getCurrentPosition(function(posicao) {
    var url = "http://nominatim.openstreetmap.org/reverse?lat="+posicao.coords.latitude+"&lon="+posicao.coords.longitude+"&format=json&json_callback=preencherDados";
});

Para chamar a URL, como estamos usando JSONP, basta criar um elemento <script> com src apontando para essa URL:

      var script = document.createElement('script');
      script.src = url;
      document.body.appendChild(script);

Na URL, definimos a função preencherDados como receptora dos dados do serviço do OpenStreetMap. Precisamos definir essa função então, que receberá os dados em formato JSON. Aí basta navegar nos dados e usá-los para preencher os campos na página. Por exemplo, se tivermos um elemento com ID campoCEP na página, faríamos:

function preencherDados(dados) {
  document.querySelector('#campoCEP').value = dados.address.postcode;  
}

O exemplo final apenas cria mais campos (rua, número, cidade, CEP) e preenche todos com base no retorno do serviço. Veja:

Veja o exemplo no CodePen.

Há muitas possibilidades de melhoria ainda, claro. Como oferecer um spinner enquanto carrega, usar um ícone de geolocalização, não exibir o botão caso o navegador não tenha suporte, preencher mais campos (estafo, país, etc).

Mas repare como pouco código já traz muito ganho de usabilidade. O usuário pode pular o preenchimento de vários campos, ganhando tempo. Algo essencial sobretudo no mobile. Repare ainda como o formulário continua editável, para o caso de erros nos dados e o usuário precisar fazer ajustes.

Nos nossos cursos de front-end estamos sempre preocupados em como fazer códigos que melhorem a interface e ainda com progressive enhancement. No curso de usabilidade, discutimos esse e outros cenários que complicam a vida do usuário e como soluções técnicas simples podem fazer grande diferença.

10 Comentários

  1. Bruno César 11/07/2015 at 21:40 #

    Muito bacana o exemplo associando o uso do recurso à experiência do usuário.

    Só um detalhe: o Google tem versão free da API, tanto client-side (limite por sessão de usuário), quanto server-side (limite de 2,5k requisições em 24h por IP, com cache).

    Nunca usei o OpenStreetMap, mas irei olhar a documentação, parece ser uma boa alternativa para alguns serviços do Google =)

  2. Harryson 12/07/2015 at 09:26 #

    Bacana demais a solução, mas na prática, acha viável o preenchimento de rua e número ou usam somente para cidade e estado? A precisão para rua e número nos meus testes não foi legal. Não testei no modo de alta precisão.

  3. Paulo Campos 14/07/2015 at 09:44 #

    Muito legal o artigo Sérgio, já tinha lido bastante sobre geolocation mas ainda não tive a oportunidade de usar.

    Uma correção, no 1º parágrafo a baixo do formulário de exemplo, logo no final onde acredito que você queria colocar “estado” está “estafo”.

    Sem mais, ótima explicação!

  4. Luiz Henrique Leme 14/07/2015 at 12:34 #

    Olá Sérgio,

    Agradeço por mais este post da Caelum, nos trazendo novas formas de implementar essa questão tão chata que é o preenchimento dos dados de Endereço.

  5. Jonathan Célio 15/07/2015 at 01:33 #

    Eu acho muito boa essa API porem ainda não é tão eficaz.
    A precisão do GPS na maioria das vezes é muito baixa, acaba cometendo o erro de inserir ruas próximas e erradas, principalmente em cidades menos populares. O que faz o usuário ficar mais frustado, já que vai ter que apagar todo o formulario.

    Para dispositivos que não tem GPS é pior ainda. Nesses casos ele aponta para a central do serviço de internet (no meu caso aqui, é a NET, aponta pra cidade vizinha). É chato.
    Tentei aplicar com um cliente em um ecommerce que vende online para todo o Brasil e seus usuarios não conseguiram utilizar.

    Para mim por enquanto o jeito mais fácil de adquirir essas informações do usuário é a partir do CEP. Se caso o cliente não saiba qual é o CEP dele deveria investir em algo que faça-o descobrir. Até porque se você precisa do seu endereço, precisa também do CEP.

  6. Jhonatan Morais 27/07/2015 at 12:25 #

    Obrigado pela dica. Muito útil.

  7. André Monjardim 13/11/2015 at 21:53 #

    Olá Sérgio, venho acompanhando algum tempo as suas dicas. Parabéns!!
    Mas tenho uma dúvida simples pra vc, mas pra mim está muito difícil de eu obter a resposta.
    Preciso montar uma estrutura simples via web mobile (não é app) para obter somente na tela a quilometragem e tempo da corrida em tempo real a partir de um (start), e ao clicar em (stop), que congele essa informação na tela para posteriormente enviar para o servidor todas as informações de partida, trajeto, finalização e tempo percorrido. Não precisa de mapa. E caso eu saia do navegador ou receba uma chamada, que essas informações não se percam e deem um prosseguimento ao reabrir. Só preciso da quilometragem rodando na tela e o tempo a partir do (start). Tem como me indicar um projeto pra eu estudar? Desde já agradeço.

  8. Rodrigo 14/02/2016 at 11:38 #

    Gostaria de saber se tem como fazer um auto complete em um único input de endereço, no meu site estou criando consulta de preços , e desejo que o cliente use o auto complete de acordo com a localização dele.
    O auto complete só funciona com o nome da rua .

  9. Rian 01/03/2016 at 03:04 #

    Sérgio, preciso tirar umas dúvidas com você. Se possível manda seu email. abração

  10. João Antonio 11/06/2016 at 18:44 #

    Api muito bom e simples de usar pois preciso apenas do Bairro, Estado e País, apenas refinei o código e coloquei para funcionar em meu sistema.

    Parabéns ao autor deste POST.

    Atenciosamente,
    João Antonio

Deixe uma resposta