Capítulo 11 Geolocalización

El uso del API de geolocalización es extremadamente sencillo. Soportado por todos los navegadores modernos, nos permite conocer la posición del usuario con mayor o menor precisión, según el método de localización utilizado. En la actualidad, disponemos de tres tecnologías para geolocalizar un usuario:

  • Vía IP: todo dispositivo que se encuentra conectado a la red, tiene asignada una dirección IP (Internet Protocol) pública que actúa, de forma muy simplificada, como un código postal. Evidentemente, esta no es la mejor manera de localización, pero sí nos da una ligera idea de dónde se encuentra.
  • Redes GSM: cualquier dispositivo que se conecte a una red telefonía, es capaz de obtener una posición aproximada basándose en una triangulación con las antenas de telefonía. Es un método sensiblemente más preciso que mediante la dirección IP, pero mucho menos que mediante GPS.
  • GPS: Global Positioning System o Sistema de Posicionamiento Global. Es el método más preciso, pudiendo concretar la posición del usuario con un margen de error de escasos metros.

El primer paso es comprobar es la disponibilidad del API de geolocalización de HTML 5 en el explorador del usuario:

if(Modernizr.geolocation) {

    alert('El explorador soporta geolocalización');} else {

    alert('El explorador NO soporta geolocalización');}

El API ofrece los siguientes métodos para geolocalizar la posición del usuario:

  • getCurrentPosition: obtiene la posición actual del usuario, utilizando la mejor tecnología posible.
  • watchPosition: consulta cada cierto tiempo la posición del usuario, ejecutando la función de callback indicada únicamente si la posición ha cambiado desde la última consulta.

Ambos métodos se ejecutan de manera asíncrona para obtener la posición del usuario. Si es la primera vez que se solicita la localización al navegador, éste mostrará un mensaje pidiendo permiso al usuario para compartir su localización. Si el usuario no da su permiso, el API llama a la función de error que hayamos definido. La especificación dice:

"El navegador no debe enviar información sobre la localización a sitios sin el permiso explícito del usuario."

Así pues, queda en manos de los navegadores informar al usuario que estamos intentando acceder a su posición actual. La forma de realizarlo depende del navegador. Por norma general, los navegadores de escritorio muestran un aviso no bloqueante, lo que permite seguir utilizando y ejecutando la aplicación.

Petición para compartir localización en Chrome

Figura 11.1 Petición para compartir localización en Chrome

En cambio, en navegadores de dispositivos móviles, como Safari y Chrome, se muestra una ventana modal que bloquea la ejecución del código hasta que el usuario acepte o deniegue la solicitud de geolocalización.

Petición para compartir localización en Safari Mobile y Chrome Mobile

Figura 11.2 Petición para compartir localización en Safari Mobile y Chrome Mobile

11.1 Métodos del API

El API de geolocalización del objeto navigator contiene tres métodos:

  • getCurrentPosition
  • watchPosition
  • clearWatch

Los métodos watchPosition y clearWatch están emparejados, de la misma manera que lo están setInterval y clearTimeout. watchPosition devuelve un identificador único, que permite cancelar posteriormente las consultas de posición pasando es identificador como parámetro a clearWatch.

Tanto getCurrentPosition como watchPosition, son métodos muy parecidos, y toman los mismos parámetros: una función de éxito, una función de error y opciones de geolocalización. Un simple ejemplo de uso del API geolocalización es el siguiente:

navigator.geolocation.getCurrentPosition(function (position) {
    alert('We found you!');
    // now do something with the position data
});

11.1.1 Función de éxito

Si el usuario permite que el navegador comparta la localización, y no se produce ningún otro error, se llama a la función de éxito, que es el primer argumento de las funciones de getCurrentPosition y watchPosition. Ésta función recibe como parámetro un objeto position que contiene dos propiedades: un objeto coords (contiene las coordenadas) una marca de tiempo timestamp. El objeto de coordenadas es el que nos interesa, ya que es el que contiene la información sobre la geolocalización. Sus propiedades son las siguientes:

  • readonly attribute double latitude
  • readonly attribute double longitude
  • readonly attribute double accuracy

La propiedad accuracy contiene la precisión de las coordenadas en metros. Podemos utilizarlo para mostrar un radio de precisión de la posición en nuestro mapa.

Aunque es complicado de confirmar, es posible que esta información de geolocalización provenga de servicios propios de los fabricantes. Por ejemplo, Google dispone de una gran base de datos, que combinado con la información de la petición (como el hardware, la dirección IP, etc.) puede dar una localización. Esta información simplemente representa la posición del usuario, y no contiene nada más que nos pueda indicar la velocidad o dirección del usuario.

Utilizando la información de posición, es muy sencillo mostrar la posición del usuario en un mapa:

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function (position) {
        var coords = position.coords;
        showMap(coords.latitude, coords.longitude, coords.accuracy);
    });
}

Existe otro tipo de datos dentro del objeto coords, para dispositivos que dispongan de GPS, aunque la gran mayoría de navegadores establecerán estas propiedades como null.

  • readonly attribute double altitude
  • readonly attribute double altitudeAccuracy
  • readonly attribute double heading
  • readonly attribute double speed

11.1.2 Obteniendo datos extra

Actualmente, muchos de los dispositivos integran un GPS. Dependiendo del navegador o del sistema operativo, la información provista con la geolocalización puede incluir mucha más información que simplemente las coordenadas de la posición, como la velocidad y la altitud.

En la mayoría de los casos, hay que especificar al API que utilice una mayor precisión para activar el GPS. Como siempre, hay que tener cuidado al utilizar el GPS, ya que consume muchísima batería y hay que utilizar esta tecnología únicamente si es estrictamente necesario.

Para calcular la velocidad, el dispositivo necesita conocer la diferencia media entre las últimas localizaciones. Por esta razón, es necesario utilizar el método watchPosition y calcular la velocidad de la siguiente manera:

var speedEl = document.getElementById(‘speed’);
navigator.geolocation.watchPosition(function (geodata) {
    var speed = geodata.coords.speed;
    if (speed === null || speed === 0) {
        speedEl.innerHTML = "You're standing still!";
    } else {
        // speed is in metres per second
        speedEl.innerHTML = speed + “Mps”;
    }
}, function () {
    speedEl.innerHTML = "Unable to determine speed :-(";
},
{ enableHighAccuracy: true }
);

11.1.3 Función de error

El segundo parámetro para los métodos getCurrentPosition y watchPosition es la función de error. Esta función es importante si queremos proveer de un segundo método alternativo para introducir la localización, por ejemplo de manera manual, o queremos informar al usuario del error. Esta función se ejecuta cuando el usuario deniega la petición de localización, o cuando estamos consultando la posición pero el dispositivo pierde la recepción de la localización. La función de error recibe un único argumento con dos propiedades:

  • readonly attribute unsigned short code
  • readonly attribute DOMString message

El código de error puede contener los siguientes valores:

  • PERMISSION_DENIED (valor = 1)
  • POSITION_UNAVAILABLE (valor = 2)
  • TIMEOUT (valor = 3)

11.1.4 Configurar la geolocalización

Finalmente, el tercer argumento para los métodos getCurrentPosition y watchPosition contiene las opciones de geolocalización. Todas estas configuraciones son opcionales, puede que no se tengan en cuenta por los navegadores.

  • enableHighAccuracy: booleano, por defecto false
  • timeout: en milisegundos, por defecto infinito
  • maximumAge: en milisegundos, por defecto 0

Por ejemplo, para solicitar una alta precisión, un timeout de dos segundos y no cachear las peticiones, llamamos al método getCurrentPosition con las siguientes opciones:

navigator.geolocation.getCurrentPosition(success, error, {
    enableHighAccuracy: true
    timeout: 2000
    maximumAge: 0
});

Ejercicio 13

Ver enunciado

Índice de contenidos