Debido al maravilloso mundo de la movilidad, HTML 5 no podía privarse de facilitar a los desarrolladores una API para poder geolocalizar a los usuarios de su aplicación web. Lo que realmente es de agradecer es la facilidad con la que podemos solicitar esta información al usuario 😀
En este punto cabe remarcar que todas aquellas APIs que necesiten interactuar con cualquier tipo de hardware de nuestro dispositivo necesitará previa autorización con el objetivo de reforzar la seguridad y el derecho a la privacidad del individuo.
Recuperando la geolocalización
Antes de obtener la información es necesario saber que la misma puede ser proporcionada desde distintos mecanismos, lo que se conoce como location providers. Los proveedores más comunes son el GPS y la IP. Los navegadores son los encargados de facilitar estos mecanismos de manera transparente para nosotros, teniendo uno de ellos por defecto. Por el momento no es posible elegir cuál de ellos utilizar en cada ocasión y queda a manos de los desarrolladores de cada plataforma determinar cuál se usará. Normalmente en los dispositivos móviles el navegador tiene por defecto el uso del GPS y, para el resto, haremos uso de la dirección IP para determinar esta localización. El navegador llamará al proveedor que le facilita la información y la compartirá a través de la petición del sitio web. Podemos comprobar el resultado a través de este sencillo ejemplo:
Al hacer clic sobre el botón se solicitará autorización para recuperar la información y acto seguido se nos mostrarán los valores. Algunos de ellos podrían no estar disponibles, dependiendo del navegador y dispositivo con el que hayamos ejecutado la prueba. En el caso de que la información haya sido recogida a través del GPS obtendremos más información que por IP.
function log(msg) { var result = document.getElementById("result"); result.innerHTML += "<li>" + msg + "</li>"; } window.onload = function() { if (navigator.geolocation) { var btnPosition = document.getElementById("btnPosition"); btnPosition.addEventListener("click", function() { navigator.geolocation.getCurrentPosition(function(data) { var coordinates = data.coords; console.log(coordinates); log("Accuracy: " + coordinates.accuracy); log("Altitude: " + coordinates.altitude); log("Altitude Accuracy: " + coordinates.altitudeAccuracy); log("Heading: " + coordinates.heading); log("Latitude: " + coordinates.latitude); log("Longitude: " + coordinates.longitude); log("Speed: " + coordinates.speed); }, function(error) { var code = error.code; switch(code){ case 0: log("Error: Unknown error"); break; case 1: log("Error: Permission denied"); break; case 2: log("Error: Position unavailable"); break; case 3: log("Error: Time out!"); } }); }); } };
La primera función que aperece en nuestro código solamente se utiliza para mostrar el resultado en un listado. Dentro del evento window.onload lo primero que debemos comprobar es si esta API está disponible para nuestro navegador a través de navigator.geolocation. Una vez comprobado, podremos asignar al evento clic del botón un manejador donde llamaremos a navigator.geolocation.getCurrentPosition, la cual recibe una función para recuperar la información en el caso de éxito y una segunda (opcional) para poder controlar los posibles errores durante la petición. Los valores que podemos obtener son siguientes:
- Accuracy: Se trata del nivel de precisión de la latitud y longitud. Se especifica en metros.
- Altitude: Nos indica la altura de la posición y sólo es proporcionada a través del GPS como mecanismo de geolocalización
- Altitude Accuracy: En este caso se nos proporciona la precisión en metros de la altitud, en el caso de tener este valor.
- Heading: En grados también se nos proporciona la dirección a la que apunta el dispositivo.
- Latitude y Longitude: Se muestran en grados decimales.
- Speed: Aunque parece increíble también se podrá conocer la velocidad. Deberá devolver los metros por segundo.
Vigilar la posición del usuario
Otra alternativa a getCurrentPosition es la posibilidad de vigilar la posición del usuario. Para ello esta API nos facilita además otra función llamada watchPosition, la cual tiene como parámetros los mismos que getCurrentPosition pero la diferencia está en que esta función llamará a sus callbacks repetidas veces permitiendo de este modo actualizar la información si el usuario se ha movido o si la precisión de los datos ha variado. La forma de invocarla es exactamente igual:
function log(msg) { var result = document.getElementById("result"); result.innerHTML += "<li>" + msg + "</li>"; } window.onload = function() { if (navigator.geolocation) { var btnWatchPosition = document.getElementById("btnWatchPosition"), btnStop = document.getElementById("btnStop"), watchID; btnWatchPosition.addEventListener("click", function() { watchID = navigator.geolocation.watchPosition(function(data) { var coordinates = data.coords; log("Watching your position"); log("Accuracy: " + coordinates.accuracy); log("Altitude: " + coordinates.altitude); log("Altitude Accuracy: " + coordinates.altitudeAccuracy); log("Heading: " + coordinates.heading); log("Latitude: " + coordinates.latitude); log("Longitude: " + coordinates.longitude); log("Speed: " + coordinates.speed); }, function(error) { var code = error.code; switch (code) { case 0: log("Error: Unknown error"); break; case 1: log("Error: Permission denied"); break; case 2: log("Error: Position unavailable"); break; case 3: log("Error: Time out!"); } }); }); btnStop.addEventListener("click", function() { log("Stop watching you"); navigator.geolocation.clearWatch(watchID); }); } };
En este caso debemos tener en cuenta un detalle adicional: Es posible que en algún momento necesitemos parar esa petición y es por ello que navigator.geolocation.watchPosition nos devuelve un ID con el que podremos parar la detección automática a través de navigator.geolocation.clearWatch(nuestroID).
Si bien hasta este punto tenemos bastante información, es importante conocer un tercer parámetro opcional, disponible para las dos funciones anteriores, con el que podremos afinar más nuestra petición. El mismo recibe un objeto donde podremos incluir los siguientes valores:
- enableHighAccuracy: Se trata de un boolean donde podemos habilitar una precisión más alta. Por motivos obvios en algunas ocasiones no tendrá efecto alguno pero si que es importante saber que puede perjudicar al estado de la batería del dispositivo. El valor por defecto es false.
- maximumAge: Podemos establecer el tiempo de expiración de una localización dada por el navegador en milisegundos. El navegador podría cachear la información para mejorar el rendimiento pero es posible controlarlo a través de esta propiedad. Su valor por defecto es cero, con lo que nunca se cacheará la información.
- timeout: Cuando lanzamos la petición el tiempo de espera debería de ser controlado. A través de esta propiedad podemos establecerlo en milisegundos. Por defecto es infinito.
Desde mi punto de vista personal, si bien es cierto que esta API puede mejorar la experiencia del usuario en nuestro sitio, deberíamos tener una alternativa en el caso de que la posición no esté disponible por diversos motivos: El usuario está buscando información de otra zona, no permite la geolocalización, han ocurrido varios timeouts, etcétera.
Espero que sea de utilidad 😀
¡Saludos!