La popularidad de los dispositivos que utilizan GPS ha multiplicado el número de usuarios que utilizan esta tecnología. El GPS se utiliza tanto para usos profesionales, civiles o militares como para usos recreativos. Como por ejemplo, los senderistas y deportistas que utilizan el GPS para grabar sus rutas.
El formato GPX es uno de los formatos vectoriales GIS más populares que está pensado para intercambiar los datos entre diferentes dispositivos. Podemos publicar en la web esos datos almacenados en formato GPX utilizando un software libre como Leaflet. Veamos cómo hacerlo.
El plugin Leaflet-omnivore
El camino más fácil para publicar los datos GPX en Leaflet es utilizar el plugin leaflet-omnivore. Este plugin, además de GPX, permite utilizar otros formatos como csv, kml, wkt. En el caso de GPX, leaflet-omnivore lo aplica mediante geoJSON.
Utilizar el plugin leaflet-omnivore es sencillísimo. Solo se requieren dos pasos:
Paso 1: Llamar al plugin mediante un enlace CDN de Mapbox:
<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-omnivore/v0.2.0/leaflet-omnivore.min.js'></script>
Paso 2. Escribir el nombre del archivo GPX que contiene los datos GPS:
omnivore.gpx('nombre_de_mi_archivo.gpx').addTo(map);
Veamos a continuación un ejemplo, en el que utilizamos un archivo GPX que contiene una etapa del Camino Santiago. Concretamente la etapa número 21 entre Astorga y el Alto de Foncebadón (León), obtenida de wikiloc.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Leaflet-omnivore</title> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/> <script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script> <script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-omnivore/v0.2.0/leaflet-omnivore.min.js'></script> <style> #map { width: 700px; height: 600px; } </style> </head> <body> <div id ="map"> </div> <script> var map = L.map('map', {center: [42.4624, -6.2073],zoom: 11}); L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map); omnivore.gpx('frances-21-astorga-foncebadon.gpx').addTo(map); </script> </body> </html>
El mapa que obtenemos es el siguiente:
El plugin leaflet-gpx es aún más interesante
Hemos visto como podemos utilizar un archivo GPX de forma rápida y sencilla con el plugin omnivore. Sin embargo con este plugin no podemos sacar partido a todas las posibilidades que nos ofrece el formato GPX. Tenemos a nuestra disposición el plugin leaflet-gpx que nos va a permitir utilizar los datos del GPX para incorporar información al mapa y hacerlo más interesante.
Como siempre lo primero es llamar al plugin. Lo hacemos mediante el siguiente enlace:
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-gpx/1.4.0/gpx.min.js"></script>
En el cuerpo del documento escribimos la instancia al plugin:
var url = 'frances-21-astorga-foncebadon.gpx'; // URL al archivo GPX new L.GPX(url, {async: true}).on('loaded', function(e) { map.fitBounds(e.target.getBounds()); }).addTo(map);
Como vemos en al apartado anterior, hemos creado una variable llamad «url» que contiene la ruta al archivo GPX. A continuación, creamos una instancia a L.GPX en donde pasamos la url y un evento. Esta parte es importante porque aquí es donde podremos utilizar las diferentes opciones de las que dispone el plugin y que nos permitirá extraer todo su potencial.
El código completo es el siguiente:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Leaflet gpx plugin basic</title> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/> <style> #map { width: 700px; height: 600px; } </style> </head> <body> <script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-gpx/1.4.0/gpx.min.js"></script> <div id ="map"> </div> <script> var map = L.map('map', {center: [42.4624, -6.2073],zoom: 11}); L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map); var url = 'frances-21-astorga-foncebadon.gpx'; // URL al archivo GPX new L.GPX(url, {async: true}).on('loaded', function(e) { map.fitBounds(e.target.getBounds()); }).addTo(map); </script> </body> </html>
En el mapa que vemos a continuación se muestra el trayecto. Si pasamos el cursor del ratón sobre la línea podemos ver información adicional incorporada en el archivo GPX y, en algunos puntos si hacemos clic se abre un popup que contiene datos y enlaces de la ruta:
Visualizando los datos
El formato GPX utiliza un esquema XML para almacenar los datos. En consecuencia es una colección de etiquetas como <name>,<ele>, <time>, etc… Estas etiquetas albergan valores útiles del trayecto que podemos extraer. Eso se puede hacer de la siguiente forma:
var url = 'frances-21-astorga-foncebadon.gpx'; // URL to your GPX file or the GPX itself new L.GPX(url, {async: true}).on('loaded', function(e) { var gpx=e.target; map.fitBounds(gpx.getBounds()); //Distancia var distance =(gpx.get_distance()); var metros= x = Math.round(distance);; document.getElementById("distancia").innerHTML ="Distancia: "+metros+" m"; //Cota inferior //get_elevation_min (): devuelve la elevación más baja, en metros var elevation_min =(gpx.get_elevation_min()); var cota_min= Math.round(elevation_min);; document.getElementById("cotamin").innerHTML ="Cota minima: "+cota_min+" m"; //Cota superior // get_elevation_max (): devuelve la elevación más alta, en metros var elevation_max =(gpx.get_elevation_max()); var cota_max= Math.round(elevation_max);; document.getElementById("cotamax").innerHTML ="Cota máxima: "+cota_max+" m"; }).addTo(map);
Estamos utilizando aquí varias de las opciones de las que dispone el plugin, como por ejemplo get_distance() que nos da el valor de la longitud total del track. Con get_elevation_min obtenemos la cota mínima del trayecto y con get_elevation_max, la cota máxima. Estos métodos son llamados desde el evento e.target. En la página del plugin se puede consultar la lista de opciones permitidas.
Utilizamos el método Math.round para redondear el valor numérico y getElementById para insertarlo en su id correspondiente.
Añadiendo marcadores
Otra de las herramientas de las que dispone el plugin leaflet-gpx es la que nos permite añadir marcadores a partir de los datos del archivo. Eso lo hacemos mediante la opción «marker_options«. Hay que escribir la url al archivo que contiene la imagen que vamos a utilizar. También podemos personalizar un marcador para el inicio de la ruta (startIconUrl), otro par el final de la ruta (endIconUrl) y otro para la sombra. En el ejemplo que escribimos a continuación hemos utilizado el marcador de Leaflet para el inicio y fin de la ruta.
new L.GPX(url, { async: true, marker_options: { startIconUrl: 'images/marker-icon.png', endIconUrl: 'images/marker-icon.png', // shadowUrl: 'images/marker-shadow.png' } }).on('loaded', function(e) { map.fitBounds(e.target.getBounds()); }).addTo(map);
Cambiando el estilo de la línea
Por último vamos a personalizar el estilo de la línea que marca la ruta. En esta ocasión la opción utilizada es»polyline_options«, donde definimos valores como el color la opacidad y el espesor de la línea. A continuación vemos un ejemplo.
new L.GPX(url, { polyline_options: { color: 'green', opacity: 0.75, weight: 3, lineCap: 'round' } }).on('loaded', function(e) { map.fitBounds(e.target.getBounds()); }).addTo(map);
El código al completo, incorporando las opciones descritas es el siguiente:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Mi primer Leaflet</title> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/> <style> #map { width: 700px; height: 600px; } </style> </head> <body> <script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-gpx/1.4.0/gpx.min.js"></script> <div id="nombre"></div> <div id="distancia"></div> <div id="cotamin"></div> <div id="cotamax"></div> <div id ="map"> </div> <script> var map = L.map('map', {center: [42.4624, -6.2073],zoom: 11}); L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map); var url = 'frances-21-astorga-foncebadon.gpx'; // URL to your GPX file or the GPX itself new L.GPX(url, { async: true, marker_options: { startIconUrl: 'images/marker-icon.png', endIconUrl: 'images/marker-icon.png', }, polyline_options: { color: 'green', opacity: 0.75, weight: 3, lineCap: 'round' }, }).on('loaded', function(e) { var gpx=e.target; map.fitBounds(gpx.getBounds()); //Distancia var distance =(gpx.get_distance()); var metros= x = Math.round(distance);; document.getElementById("distancia").innerHTML ="Distancia: "+metros+" m"; //Cota inferior //get_elevation_min (): devuelve la elevación más baja, en metros var elevation_min =(gpx.get_elevation_min()); var cota_min= Math.round(elevation_min);; document.getElementById("cotamin").innerHTML ="Cota minima: "+cota_min+" m"; //Cota superior // get_elevation_max (): devuelve la elevación más alta, en metros var elevation_max =(gpx.get_elevation_max()); var cota_max= Math.round(elevation_max);; document.getElementById("cotamax").innerHTML ="Cota máxima: "+cota_max+" m"; }).addTo(map); </script> </body> </html>
Y el resultado es el que se muestra en el siguiente mapa:
Si quieres aprender a crear visores web profesionales como estos, inscríbete ya en nuestro curso online visores webmapping con Leaflet.
Tutor del curso online de Análisis GeoEspacial con Python y de los cursos online de webmapping. Echa un vistazo a todos nuestros cursos de SIG online.
Hola y nuevamente gracias por el tiempo que usas en compartir, mi pregunta es si existe la manera de hacer que leaflet pueda mostrar una posicion en «tiempo real», ya sea un plugin o un metodo con php o js.
Les agradeceria algo de orientacion
Buenos días Goxalo:
Puedes utilizar la Geolocation API con Leaflet para obtener la ubicación en cada momento de un usuario. Tienes un ejemplo en este mismo blog. https://mappinggis.com/2016/09/un-mapa-de-leaflet-en-el-movil-ajuste-y-geolocalizacion/. Otra cuestión es que quieras grabar esas posiciones, lo cual requerirá un desarrollo mayor, en el que seguramente necesites utilizar alguna base de datos y conexiones con PHP.
Saludos
Hola y gracias por tus enseñanzas, son muy valiosas.
Aunque tal vez este comentario sea mas bien para un foro de js, igual te pregunto,
el ejemplo me funciona muy bien, pero quiero ponerlo en un grupo de layes y seleccionarlo, pero no doy con la manera de hacerlo.
Espero tu ayuda
Estimado Goxalo, en la documentación de Leaflet hay un ejemplo muy bueno de layer groups. https://leafletjs.com/examples/layers-control/. Este ejemplo te puede servir de orientación para crear un grupo de capas y un control de capas.
Saludos
Gracias Gonzalo por tu comentario.
La página que adjuntas es un buen ejemplo de lo que se puede hacer con Leaflet.
Leaflet es una librería sencilla pero que ofrece muchos recursos.
Saludos
Buen aporte!!.
Actualmente multitud de rutas desbordan las webs de turismo activo. Wikiloc sigue siendo el gran repositorio de información de rutas. Parece que no acaban de llegar los simples, ligeros y útiles visores como Leaflet a los centros productores y difusores de toda esa inmensa cantidad de geoinformación. Un sencillo visor no oficial par varias de la rutas de BTT ofertadas por el consorcio turístico de Tierra Estella en Navarra…
https://www.napargis.com/btt/RutasBTT.html