La API ( Application Programming Interface ) de geolocalización permite al usuario compartir su ubicación con las aplicaciones web.
Por razones de seguridad, el navegador pide permiso para utilizar la ubicación del usuario, y la posición no está disponible a menos que el usuario lo aprueba.
Una primera prueba
A continuación vamos a realizar una prueba para ver de que va la geolocalización. En el HTML ( un HTML minimalista ) hay un enlace hacia un archivo externo de JavaScript ( geo.js
) y un <div id = "ubicacion">
<!doctype html> <html><head><meta charset="UTF-8"><script src="geo.js"></script></head><body> <div id="ubicacion"> Tus coordenadas aparecerán aquí </div></body>
Ahora vamos a crear geo.js
Cuando la página esté cargada ( window.onload
) el JavaScript llama la función miUbicacion()
.
window.onload = miUbicacion;
Si los servicios de geolocalización están disponibles ( if(navigator.geolocation)
) vamos a utilizar el métodogetCurrentPosition()
( literalmente: traiga la ubicación actual ) para... obtener la ubicación actual.
La función muestraMiUbicacion()
es un gestor ( handler ) que será llamado si hay éxito. El gestor devuelve un objeto que almacena la posición actual: la latitud: posicion.coords.latitude
y la longitud:posicion.coords.longitude
entre otras.
La posición actual saldrá como contenido ( innerHTML
) en el <div id="ubicacion">
// llama la función miUbicacion cuando la página este cargada window.onload = miUbicacion;function miUbicacion(){ //Si los servicios de geolocalización están disponibles if(navigator.geolocation){ // Para obtener la ubicación actual llama getCurrentPosition. navigator.geolocation.getCurrentPosition( muestraMiUbicacion ); }else{ //de lo contrario alert("Los servicios de geolocalizaci\363n no est\341n disponibles"); }}function muestraMiUbicacion(posicion){ var latitud = posicion.coords.latitude var longitud = posicion.coords.longitude var output = document.getElementById("ubicacion"); output.innerHTML = "Latitud: "+latitud+" Longitud: "+longitud;}
Cuando ejecutamos por la primera vez el app ( de application ) de geolocalización, el navegador nos pide permiso para utilizar nuestra ubicación. Podemos, naturalmente, denegar el permiso, pero suponiendo que estamos de acuerdo, en unos cuantos segundos el contenido ( innerHTML
) del <div id="ubicacion">
cambiará, y podremos ver las coordenadas de nuestra ubicación ( latitud y longitud ).
El formato en el que aparecen es por defecto es DDD ( Decimal degrees ). Veremos más tarde como cambiarlas para que aparezcan en grados minutos y segundos.
Latitud: 43.3648568 Longitud: -2.9935058
¿Qué problemas pueden aparecer?
Podemos encontrarnos con que el usuario utiliza un navegador muy antiguo, o que el usuario denegó el permiso para utilizar su ubicación. Cabe la posibilidad que la posición del dispositivo no pude ser determinada, o que se agotó el tiempo de espera permitido.
Para entender las problemas que pueden aparecer y como salir con elegancia de esto – siga leyendo....
La geolocalización parece no funcionar en Firefox para Mac o Linux. Este es un enlace que nos permite verificar si la geolocalización funciona en el navegador que utilizamos: http://html5demos.com/geo
El método getCurrentPosition()
se utiliza para obtener la posición de un dispositivo.
Si hay éxito
La función siHayExito
es un gestor ( handler ) y será llamada si hay éxito. Toma como único argumento el objetoposicion
("p" en la siguiente tabla que detalla las propiedades de la posicion
).
navigator.geolocation.getCurrentPosition( siHayExito, enCasoDeError ( opcional ), opciones ( opcional ) );
Si hay éxito podemos recuperar la latitud y la longitud ( podemos recuperar mucho más ) mediante la funciónsiHayExito()
, y sacarlo en pantalla como contenido ( innerHTML
) del <div id="ubicacion">
.
// la función muestraMiUbicacion ahora se llama siHayExitofunction siHayExito(posicion){ var latitud = posicion.coords.latitude var longitud = posicion.coords.longitude var output = document.getElementById("ubicacion"); output.innerHTML = "Latitud: "+latitud+" Longitud: "+longitud;}
En caso de error
La función enCasoDeError
( opcional ) es una función de gestión de errores ( error handler ), que será llamada en caso de error.
Toma como único argumento el objeto "error" ( "e" en la siguiente tabla ) que contiene un código numérico que corresponde al tipo de error ocurrido.
Por alguna parte dentro del HTML pondremos un <div id="ubicacion">
que utilizaremos para sacar el resultado en pantalla.
<!doctype html> <html><head><meta charset="UTF-8"><script src="geo.js"></script></head><body> <div id="ubicacion"> Tus coordenadas aparecerán aquí </div></body></html>
La función siHayError
La función siHayError()
contiene un objeto ( posiblesErrores
) que "traduce" el código de error ( error.code
) al castellano.
Cuando el error.code == 0
o error.code == 2
habrá información adicional ( en inglés ) y es posible que nos interese conocerla, al menos en la etapa de desarrollo.
Al final sacaremos el mensaje de error en pantalla como innerHTML
del <div id="ubicacion">
.
function siHayError(error){//errorHandler// el objeto posiblesErrores traduce al castellano los posibles errores var posiblesErrores = { 0:"Error desconocido", 1:"Permiso denegado por el usuario.", 2:"Posici\363n no disponible", 3:"Desconexi\363n por tiempo" } var mensajeError = posiblesErrores[error.code]; // error.message : información adicional if(error.code == 0 || error.code == 2){ mensajeError = mensajeError +" "+error.message; } var div = document.getElementById("ubicacion"); div.innerHTML = mensajeError;}
La función siHayError ( otra variante )
Si queremos podemos utilizar un switch
en lugar del objeto posiblesErrores
con el mismo propósito. Esta vez vamos a utilizar la constante asociada en lugar del código numérico.
function siHayError(error){//errorHandler// traduce al castellano los posibles errores switch(error.code){ case error.PERMISSION_DENIED: mensajeError = "Permiso denegado por el usuario." break; case error.POSITION_UNAVAILABLE: mensajeError = "Posici\363n no disponible."+" "+error.message; break; case error.TIMEOUT: mensajeError = "Desconexi\363n por tiempo." break; case error.UNKNOWN_ERROR: mensajeError = "Error desconocido."+" "+error.message; break; } var div = document.getElementById("ubicacion"); div.innerHTML = mensajeError;}
Opciones ( parámetro opcional )
Cada navegador interpreta estas opciones a su manera, y por ahora son más indicios que indicaciones.
En principio, con este parámetro ( options ) podemos controlar la precisión ( accuracy
), el tiempo máximo alocado para calcular las coordenadas.
var opciones = {enableHighAccuracy: false, timeout: Infinity, maximumAge: 0}
enableHighAccuracy: puede ser true
o false
.
Si enableHighAccuracy: true
indicamos a la aplicación que queremos el máximo de precisión ( accuracy ) posible. Esto puede ser muy útil si queremos localizar la ubicación del usuario a nivel calle ( por ejemplo ), aunque – puede ser también uninconveniente ya que puede causar tiempos de respuestas mas lentos, y en el caso de los dispositivos móviles puede agotar la batería.
timeout: El valor de timeout
se da en milisegundos , e indica el tiempo máximo de espera antes de llamar la función siHayError
. Por ejemplo si timeout: 10000
( 10 segundos ) la aplicación esperará 10 segundos por una respuesta. Si en 10 segundos no hay respuesta, llamará la función siHayError
y tendremos "desconexión por tiempo"
. Por defecto timeout: Infinity
.
maximunAge: es el tiempo máximo durante el cual la información guardada en el caché puede ser aprovechada. Un valor de maximumAge : 0
obliga el navagador a recalcular la ubicación cada vez que llamamos el métodogetCurrentPosition()
.
Poniendolo todo junto
<!doctype html> <html><head><meta charset="UTF-8"><script src="geo.js"></script></head><body> <div id="ubicacion"> Tus coordenadas aparecerán aquí </div></body></html>
window.onload = miUbicacion;function miUbicacion(){ // Si los servicios de geolocalización están disponibles if(navigator.geolocation){ // Para obtener la ubicación actual llama getCurrentPosition. navigator.geolocation.getCurrentPosition( siHayExito, siHayError, {enableHightAccuracy: false, timeout:Infinity, maximage:0} ); }else{ alert("Los servicios de geolocalizaci\363n no est\341n disponibles"); }}function siHayExito(posicion){ var latitud = posicion.coords.latitude var longitud = posicion.coords.longitude var output = document.getElementById("ubicacion"); output.innerHTML = "Latitud: "+latitud+" Longitud: "+longitud;}function siHayError(error){//errorHandler// el objeto posiblesErrores traduce al castellano los posibles errores var posiblesErrores = { 0:"Error desconocido", 1:"Permiso denegado por el usuario.", 2:"Posici\363n no disponible", 3:"Desconexi\363n por tiempo" } var mensajeError = posiblesErrores[error.code]; // error.message : información adicional if(error.code == 0 || error.code == 2){ mensajeError = mensajeError +" "+error.message; } var div = document.getElementById("ubicacion"); div.innerHTML = mensajeError;}
Latitud: 43.3648646 Longitud: -2.9933848999999997
La geolocalización parece no funcionar en Firefox para Mac o Linux. Este es un enlace que nos permite verificar si la geolocalización funciona en el navegador que utilizamos: http://html5demos.com/geo
Un poco de geografía
La latitud se mide en grados sexagesimales y puede representarse de dos formas:
1. Indicando a qué hemisferio (N o S) pertenece la coordenada.
La latitud de Barcelona es de 41.3833° N
La latitud de Melbourne es de 37.8136° S
2. Dejando las latitudes nórdicas como números positivos, y escribiendo las latitudes sureñas como números negativos.
La latitud de Barcelona es de 41.3833°
La latitud de Melbourne es de -37.8136°
La longitud se mide también en grados sexagesimales y también puede representarse de dos formas:
1. Indicando a qué hemisferio (E o W) pertenece la coordenada.
La longitud de Barcelona es de 2.1833° E
La longitud de Madrid es de 3.6833° W
2. Dejando las longitudes al Este del meridiano de Greenwich como números positivos, y escribiendo las longitudes al Oeste del meridiano de Greenwich como números negativos.
La longitud de Barcelona es de 2.1833°
La longitud de Madrid es de -3.6833°
Podemos conseguir fácilmente las coordenadas de un punto haciendo clic con el botón derecho del ratón enGoogle maps y escogiendo "que hay aquí"
Quiero las coordenadas en grados, minutos y segundos
Es verdad. El formato en el que aparecen las coordenadas en Google es por defecto es DDD ( Decimal degrees ), y es así como las necesitamos para poder calcular el valor del ángulo en radianes.
Es bastante fácil transformar las coordenadas de DMS ( grados ( degrees ) minutos y segundos ) a DDD
Ejemplo práctico: de DMS a DDD
La latitud de un punto en Barcelona es de 41º 24' 58''
var DDD = 41 + ( 24 / 60 ) + ( 58 / 3600 ) = 41.41611111111111
Es un poco más complicado transformar las coordenadas de DDD a DMS ( grados ( degrees ) minutos y segundos )
Ejemplo práctico: de DDD a DMS
La latitud de un punto en Barcelona es de 41.3827°
<p>Grados: <span id="deg"></span><br> Minutos: <span id="min"></span><br> Segundos: <span id="sec"></span></p>
function deDDDaDMS( lat ){ var deg = Math.floor( lat ); var modulus = lat % 1; var minutes = Math.floor( modulus * 60 ); if( minutes == 60){ deg +=1; minutes = 0;} var sec = Math.ceil( ( modulus*60 % 1 ) * 60 ); if( sec == 60){ minutes +=1; sec = 0;} document.getElementById("deg").innerHTML=deg; document.getElementById("min").innerHTML=minutes; document.getElementById("sec").innerHTML=sec;}var lat = 41.3827;//llama la función deDDDaDMSdeDDDaDMS(lat);
Grados: 41
Minutos: 22
Segundos: 58
Un poco de geometría
Para calcular la distancia entre dos puntos sobre una esfera hay que saber trigonometría esférica. O no.
El internet es una fuente ilimitada de recursos donde podemos encontrar de todo, incluso fórmulas que nos ayudan a calcular la distancia entre dos puntos sobre una esfera.
var distancia = Math.acos( Math.sin(lat1)*Math.sin(lat3) + Math.cos(lat1)*Math.cos(lat3) * Math.cos(long3-long1) ) * R;');
Donde
R = 6371
y es el radio de la tierra en km
lat1
y long1
son la latitud y la longitud del punto P1 en radianes
lat2
y long2
son la latitud y la longitud del punto P2 en radianes
Calcular la distancia entre dos puntos P1 y P2
Por alguna parte dentro del HTML pondremos un <span id="distancia">
que utilizaremos para sacar el resultado en pantalla.
<p>Distancia entre Barcelona y Madrid es de <span id="distancia"></span></p>
La función graRad()
transforma grados en radianes.
La función calculaDistancia(desde, hasta)
calcula la distancia entre dos puntos, en este caso entre Barcelona y Madrid.
Para esto la función transforma primero las latitudes y las longitudes de grados a radianes y después calcula la distancia y al final saca el resultado en pantalla.
function calculaDistancia(desde, hasta){ // transforma grados en radianes var lat1 = graRad(desde.lat); var long1 = graRad(desde.long); var lat2 = graRad(hasta.lat); var long2 = graRad(hasta.long); // calcula la distancia var d = Math.acos( Math.sin(lat1)*Math.sin(lat2) + Math.cos(lat1)*Math.cos(lat2) * Math.cos(long2-long1) ) * 6371; var distancia = document.getElementById("distancia") distancia.innerHTML = d.toFixed(2)+"km"; } function graRad(grados){ var radianes = (grados * Math.PI)/180; return radianes;}var Barcelona ={lat : 41.3833, long : 2.1833}var Madrid ={lat : 40.4000, long : -3.6833}calculaDistancia(Barcelona, Madrid);
Distancia entre Barcelona y Madrid es de 505.00km
La geolocalización parece no funcionar en Firefox para Mac o Linux. Este es un enlace que nos permite verificar si la geolocalización funciona en el navegador que utilizamos: http://html5demos.com/geo
Artículos relacionados
Enlaces útiles
- Para saber más sobre Math.acos: Arcocosen
- Como dar permiso para utilizar nuestra ubicación