Cómo geoposicionar a los usuarios de tu aplicación Web

18/01/2022
Artículo original

Imagen ornamentalHace ya muchos años que se popularizaron los dispositivos móviles, los cuales se pueden utilizar en cualquier lugar. Por ello, averiguar en dónde nos encontramos ha sido una de las funcionalidades básicas que muchas aplicaciones implementan. Desde la cámara de fotos que registra en qué lugares se han tomado las instantáneas, hasta aplicaciones muy especializadas que usan la ubicación para ofrecernos información, prestar servicios de transporte, medir desempeños en el deporte, etc... Ubicar al usuario es de gran utilidad.

Al proceso de ubicar un determinado dispositivo geográficamente se le denomina Geolocalización o Geoposicionamiento.

Las aplicaciones web también pueden sacar mucho partido de la información de posicionamiento de sus usuarios. Imaginemos la típica web de localización de lugares de ocio o de viajes, por ejemplo. En este tipo de aplicaciones la posición es un parámetro esencial a la hora de proporcionar el servicio.

Es por esto que todos los navegadores modernos ofrecen soporte para obtener la ubicación de los usuarios. Incluso los de escritorio, en ordenadores convencionales. No hace falta que sean dispositivos móviles ni que tengan GPS incorporado. De hecho la precisión que ofrece un navegador de escritorio sobre un ordenador de sobremesa normal es muy elevada.

Para unificar la manera de obtener acceso a los datos de ubicación, el World Wide Web Consortium (W3C) definió la API de Geolocalización dentro del estándar de HTML5. A través de esta podemos obtener la posición de un usuario en un momento determinado e incluso seguirla a intervalos regulares para trazar un mapa de movimiento.

Esta API es independiente del medio que se haya utilizado para averiguar la posición. Es decir, funciona exactamente igual si se usa un GPS, las señales de Wifi o cualquier otro sistema de obtención, lo cual facilita su uso. Además, dado que averiguar la posición del usuario es un proceso que puede tardar un cierto tiempo, la API se comporta siempre de manera asíncrona, de modo que no bloquea la ejecución de ningún script ni tampoco bloquea la interfaz de usuario.

ATENCIÓN: los navegadores sólo permiten el uso de la API de geolocalización a través de conexiones seguras basadas en HTTPS, por lo que si colocas tu código en un dominio HTTP no te funcionará. Una excepción habitual es el equipo local (127.0.0.1 o locahost), de manera que los navegadores permiten utilizarla a la hora de desarrollar.

A continuación tienes un vídeo práctico en el que te explico cómo utilizar la API de geolocalización. Con ese vídeo aprenderás lo fundamental. Para obtener todos los detalles y descargar el código de ejemplo, lee la explicación detallada que va a continuación del vídeo:

[youtube:mONXtKKaV_w]

Uso de la API de geolocalización

La API de geolocalización de HTML5 es de las APIs más sencillas de utilizar de manera directa. Quizá tenga más dificultad operar con los resultados obtenidos, ya que las matemáticas asociadas con la medida de distancias y otras cuestiones propias de la geometría terrestre pueden llegar a ser complicadas.

Toda la funcionalidad de la API depende de la propiedad geolocation del objeto navigator de la ventana actual del navegador. Esta propiedad devuelve un objeto que, con un par de métodos sencillos, nos permite acceder a toda la funcionalidad.

Este objeto está soportado en todos los navegadores desde hace muchos años, por lo que solo los navegadores más antiguos (Internet Explorer 8 o anterior en el escritorio) tendrán dificultades en utilizarla.

Podemos determinar si el navegador actual soporta la funcionalidad simplemente verificando la presencia o no de la propiedad geolocation, así:

if (navigator.geolocation) {
    //Funcionalidad propia de la API de geo-localización
}
else {
   //Mostrar un mensaje o tomar alguna acción para el caso de no estar soportada la API
}

Y aunque hoy en día es prácticamente innecesario hacerlo, dado que no cuesta nada, se considera una buena práctica incluir esta comprobación.

Obteniendo la posición actual del usuario

Una vez que hemos comprobado que la API está soportada, podemos intentar obtener la posición actual del usuario mediante la función getCurrentPosition que, como indicaba antes, es asíncrona y toma tres parámetros:

  • Función callback para obtener la posición: obligatoria. Se trata de la función que el navegador va a llamar en cuanto haya logrado obtener la posición. A través de esta función se reciben los datos detallados de la posición, como veremos enseguida.

  • Función callback para cuando hay errores: opcional. En este caso es la función que llamará el navegador en caso de que se haya producido cualquier error a la hora de obtener la posición, por cualquier motivo (el usuario no lo permite, no se ha podido obtener, etc..). Aunque es opcional es más que recomendable utilizar este parámetro siempre, y gestionar así los posibles errores y excepciones.

  • Objeto con opciones: opcional. Un objeto que puede tener una o varias propiedades diferentes que luego veremos, indicando ciertas opciones relacionadas con el proceso (como la precisión, el tiempo máximo de espera, etc...).

Así, el código más sencillo que podríamos escribir es el siguiente:

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(muestraPosicion);
}

function muestraPosicion(pos){
  alert(`Tu posición es: (${position.coords.latitude}, ${position.coords.longitude})`);
}

Lo que hace es simplemente obtener la posición y mostrarla por pantalla.

La función de callback a la que llama el navegador cuando tiene la ubicación, recibe como parámetro un objeto de tipo GeolocationPosition que ofrece dos propiedades:

  • timestamp: se trata de la fecha y hora a la cual se ha obtenido la posición. Se ofrece en forma de tipo DOMTimeStamp, que en realidad es un número de milisegundos desde el epoch de JavaScript, por lo que es equivalente a un objeto Date de JavaScript, y podemos procesarlo de la siguiente manera: var fechaMedicion = new Date(pos.timestamp); para luego poder operar con él como con cualquier otra fecha.

  • coords: esta propiedad contiene un objeto que representa a través de sus propiedades los diferentes datos de la posición actual, a saber:

    • latitude: latitud de la posición en grados sexagesimales (los habituales en las coordenadas GPS). Siempre está disponible si el método ha funcionado.

    • longitude: longitud de la posición en grados sexagesimales. Siempre está disponible si el método ha funcionado.

    • accuracy: la precisión, en metros, de la posición obtenida. De este modo podemos saber en cuánto nos podemos equivocar como máximo en la determinación de la ubicación. Siempre está disponible.

    • altitude: la altitud sobre el nivel del mar. No siempre está disponible, ya que depende de las capacidades del dispositivo en el que se ejecuta nuestra aplicación Web.

    • altitudeAccuracy: la precisión en metros de la altitud, en caso de estar disponible.

    • heading: en los sistemas que además disponen de brújula (la mayor parte de los móviles de gama media/alta), nos ofrece el ángulo en grados sexagesimales (medido en sentido horario) respecto al norte geográfico (o norte verdadero) hacia dónde apunta actualmente el usuario. Útil, si se proporciona, para sistemas que dependen de la dirección del movimiento del usuario (por ejemplo para localizar algún elemento cercano en su dirección y cosas así). No siempre está disponible.

    • speed: si nos lo facilita, mide la velocidad actual del usuario en metros por segundo. No siempre está disponible.

Con estos datos, como vemos en el ejemplo anterior, es fácil obtener la posición y otra información interesante.

Gestionando excepciones

La API de geolocalización no puede obtener la información sobre la ubicación a menos que el usuario lo consienta previamente. Para ello, la primera vez que se intenta obtener dicha posición, el navegador advierte al usuario de nuestra intención y le pregunta si desea permitirlo o no.

En cada navegador e incluso versión de este el método para preguntarlo varía, pero básicamente se muestra siempre un diálogo no intrusivo de confirmación:

Los diálogos de permisos de geolocalización de Chrome y de Firefox

En caso de que el usuario no acepte se produce una excepción que debemos capturar. Para esto y para todas aquellas situaciones en las que no se pueda obtener la posición por algún motivo, se utiliza el segundo parámetro de getCurrentPosition.

Este parámetro es la referencia a una función de callback que se llamará en caso de producirse una excepción, y a la que se le pasará como parámetro un objeto GeolocationPositionError que tiene dos propiedades:

  • code: es un código numérico que nos indica qué tipo de excepción se ha producido.
  • message: un mensaje de texto describiendo textualmente la excepción (en el idioma del navegador del usuario). Como cada navegador ofrece frases diferentes suele ser más recomendable gestionar el código numérico y mostrar un mensaje propio y siempre igual en función de cada caso, dejando este valor para logs internos o para mostrarlo por consola como una advertencia para depuración.

El código de la excepción puede tomar uno de los siguientes valores, que son además propiedades de la clase GeolocationPositionError, para facilitar la legibilidad en lugar de tener que usa directamente el número:

  • UNKNOWN_ERROR (0): error desconocido a la hora de determinar la posición. El navegador no ha podido hacerlo pero no sabe exactamente por qué.
  • PERMISSION_DENIED (1): el usuario ha denegado el permiso para poder obtener la ubicación actual. Muy típico y debemos gestionarlo adecuadamente siempre.
  • POSITION_UNAVAILABLE (2): el dispositivo (o el navegador) no ha podido determinar la posición actual debido a que no tiene señales o indicaciones suficientes para hacerlo.
  • TIMEOUT (3): el dispositivo no pudo obtener la posición dentro del intervalo de tiempo máximo de espera que se haya especificado (o que tenga por defecto). Puede ocurrir por ejemplo si se tarda mucho tiempo en ubicar los satélites GPS para calcular la posición.

Este es un ejemplo de código sencillo para obtener la posición y gestionar los posibles errores o excepciones que se pueden producir:

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(muestraPosicion, errorPosicion);
}

function muestraPosicion(pos){
  alert('Te encuentras en las siguientes coordenadas: (' + position.coords.latitude + ', ' + position.coords.longitude + ')' );
}

function errorPosicion(err) {
    switch(err.code) {
        case err.PERMISSION_DENIED:
            alert("Debe usted permitir el acceso a su posición para que la aplicación pueda funcionar");
            break;
        case err.POSITION_UNAVAILABLE:
            alert("La información sobre su posición actual no está disponible");
            break;
        case err.TIMEOUT:
            alert("No he podido obtener su posición en un tiempo razonable");
            break;
        default:
            alert("Se ha producido un error desconocido al intentar obtener la posición actual");
            break;
    }
}

Con esto tendremos cubiertas las posibles contingencias.

Te dejo aquí el código de ejemplo utilizado en el vídeo (ZIP - 1.63 Kb).

¡Espero que te resulte útil!