Leaflet es una librería de código abierto para trabajar con mapas interactivos. Es fácil de programar, fácil de utilizar y con muy buen rendimiento.
Durante la transición de OpenLayers 2 a 3, que ha supuesto aproximadamente 2 años de trabajo (de 2011 a 2014), y gracias a su simplicidad se ha convertido en la librería de web mapping preferida de los desarrolladores y proyectos fuera del área de conocimiento de los sistemas de información geográfica.
Nota: existe un plugin de QGIS, qgis2leaf, para convertir un proyecto qgis en un mapa Leaflet para publicar en la web
El objetivo del proyecto es mantener una lista de funcionalidades básicas para mantener la librería simple y de reducido tamaño.
La funcionalidad del núcleo de la librería se puede ampliar mediante plugins.
Dispone de un manual de referencia bien escrito y actualizado.
Dispone de tutoriales, con pocos ejemplos y demasiado simples.
div
que será el contenedor del mapa. Mediante estilos CSS
se configura su tamaño<!DOCTYPE html>
<html>
<head>
<title>Hello Map</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style type="text/css">
.mapas {
width: 600px;
height: 500px;
}
</style>
</head>
<body>
<div id="miMapa" class="mapas"></div>
<script>
// Crea un mapa y inicializa su posición y escala
var map = L.map('miMapa').setView([39.57, 3.0], 8);
// Crea capa openstreetmap y la añade al mapa
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors'
}).addTo(map);
</script>
</body>
</html>
CodePen es una herramienta de desarrollo web que permite a sus usuarios crear conjuntos de código HTML
, CSS
y JavaScript
(pens) para demostraciones, educación, compartición de código...
El primer mapa con Leaflet en CodePen:
See the Pen Hello Map by Xisco Guaita (@xguaita) on CodePen.
Ejercicio: Cambiar la localización del mapa a
[41.5025, 2.109]
y el nivel de zoom a17
Ejercicio: Añadir una marca de la localización del Curso JavaScript, utilizamos el objeto Marker:
// Crea marcador var ligit = L.marker([41.5026, 2.1089], {title: 'Curso JavaScript'}) .addTo(map);
Ejercicio: Añadir un popup a la marca, utilizamos el objeto Popup:
// Añade popup ligit.bindPopup('<strong>Curso JavaScript</strong><p>MTIG-17<br>LIGIT - UAB</p>');
Leaflet trabaja por defecto con el sistema de referencia Spherical Mercator (código EPSG:3857), proyección utilizada por los mapas de Google, Bing, OpenStreeMap... y caracterizada por representar la Tierra mediante una esfera en lugar de un elipsoide; de esta manera se simplifican los cálculos pero a costa de errores de posicionamiento.
También define el sistema de referencia World Geodetic System (WGS) establecido en 1984 y revisado en 2004 (código EPSG:4326); según la gente de Leaflet "A common CRS among GIS enthusiasts"; para el resto, el sistema de referencia mundial de uso estándar en cartografía, geodesia y navegación (GPS).
Para utilizar otros sistemas de referencia se ha de utilizar el plugin Proj4Leaflet, como veremos más adelante.
El objeto Map es la clase central de la librería.
Define propiedades y métodos para crear y manipular mapas:
Ejercicio: Seguiendo con el ejemplo anterior, modificar el mapa para que se comporte como un mapa fijo (no interactivo) que simplemente muestra la ubicación del LIGIT (nivel de zoom a 11):
// Como opciones del mapa { dragging: false, touchZoom: false, scrollWheelZoom: false, doubleClickZoom: false, boxZoom:false, tap:false, keyboard: false, zoomControl: false }
Los controles sirven para que el usuario interactúe con el mapa y las capas, y para mostrar información. Leaflet define sólo 4 controles.
El Control.Zoom, que ya conocemos.
Un control para mostrar la autoría de los datos y capas, Control.Attribution.
Un control de gestión de capas (Control.Layers) que nos permite, de forma sencilla, configurar las capas base del mapa (mapa de fondo, sólo una capa visible en cada momento) y las de superposición (se visualizan sobre la capa base).
Y un control que muestra la escala gráfica del mapa, Control.Scale.
Veamos un ejemplo:
See the Pen Leaflet layer control by Xisco Guaita (@xguaita) on CodePen.
Leaflet, como todas las librerías de web mapping, diferencia entre 2 tipos de capas: ráster y vectoriales. Las primeras visualizan imágenes, y las segundas trabajan con datos (puntos, líneas o polígonos) y los visualizan mediante estilos.
El núcleo de Leaflet define 3 tipos:
Mediante plugins se puede acceder a más tipos de capas: WMTS, ArcGIS Rest...
Todos los mapas que hemos generado hasta el momento han utilizado este tipo de capa. Cargan tiles de los diferentes servicios de publicación disponibles (libres o de pago), la mayoría renderizan el mapa a partir de la base de datos de OpenStreetMap o imágenes satélite.
Nota: Un buen sitio para empezar si teneis interés en crear vuestro propio servicio de mapas a partir de la base de datos de OpenStreetMap es switch2osm
Si lo que quereis es publicar vuestros propios datos, probablemente un buen punto de partida sea TileMill
Para crear una capa del tipo TileLayer:
L.tileLayer(urlTemplate, options?)
http://{s}.tile.osm.org/{z}/{x}/{y}.png
, donde {s} es el subdominio (por defecto a, b, c), {z} el nivel de zoom y {x}, {y} las coordenadas del tileExiste un plugin leaflet-providers que proporciona configuraciones de muchos proveedores de tiles. Dispone de un mapa de muestra donde se pueden ver todas las capas disponibles con su denominación (si se utiliza el plugin) y su configuración (si no se utiliza). El ejemplo anterior utilizando este plugin quedaría así:
See the Pen Leaflet leaflet-providers plugin by Xisco Guaita (@xguaita) on CodePen.
Mediante el objeto LayerGroup se pueden agrupar capas.
Modificar la línea 19 del ejemplo con el código siguiente:
// Grupo de capas var owm_pressure_cntr = L.layerGroup([ L.tileLayer.provider('OpenWeatherMap.Pressure'), L.tileLayer.provider('OpenWeatherMap.PressureContour') ]);
Extiende la capa TileLayer
para recuperar los tiles mediante un servicio WMS. Para crear una capa TileLayer.WMS:
L.tileLayer.wms(urlWMS, options)
See the Pen Leaflet WMS by Xisco Guaita (@xguaita) on CodePen.
Los servicios WMS pueden servir la información en los sistemas de referencia que consideren oportuno; pero deben servir las capas, como mínimo, en WGS84 coordenadas geográficas (epsg:4326). Veamos un ejemplo:
See the Pen Leaflet WMS epsg:4326 by Xisco Guaita (@xguaita) on CodePen.
Nota: existe un plugin con funcionalidad avanzada WMS, leaflet.wms
- single tile
- GetFeatureInfo
Carga imágenes individuales en el mapa: planos georeferenciados, imágenes aéreas... Para crear una capa ImageOverlay:
L.tileLayer.wms(urlImagen, bbox, options)
See the Pen Leaflet ImageOverlay by Xisco Guaita (@xguaita) on CodePen.
Además de visualizar capas de información geográfica en formato imagen (ráster), podemos cargar capas de datos vectoriales (puntos, líneas y polígonos) y son las propias librerías, mediante la definición de estilos, las encargadas de dibujar los elementos.
Leaflet tiene una particular manera de definir las capas vectoriales. Cada tipo de geometría básico es un tipo de capa; capas de un único elemento:
See the Pen Leaflet vector layers by Xisco Guaita (@xguaita) on CodePen.
Para poder tener más de un elemento en la misma capa, y que compartan estilo y popups, Leaflet define FeatureGroup para poder agrupar geometrías.
Ejercicio: Eliminar (borrar) las 3 capas del ejemplo anterior y sustituirlas por una capa de grupo a la que añadiremos un popup.
// Crea grupo de elementos L.featureGroup([ L.circleMarker([39.96136585349993,3.212277889251709],{ radius: 7 }), L.polyline([ [39.71590222679897,3.478717803955078], [39.56464344273239,2.3466968536376953] ], { color: "#800", dashArray: "5,10", clickable: false }), L.polygon([ [39.21602929971835,2.9724884033203125], [39.21576330385492,2.9975509643554683], [39.106886525487596,2.9975509643554683], [39.10741934019969,2.89764404296875], [39.15748593718304,2.896270751953125], [39.21602929971835,2.9724884033203125] ], { color: "#090", fillOpacity: 0.1 }) ]).bindPopup('Mensaje para todos los elementos!').addTo(map);
GeoJson es un formato abierto (bajo licencia Creative Commons) para codificar elementos geográficos simples y sus propiedades mediante JSON (la notación de objetos JavaScript), por lo que se convierte en el formato ideal para trabajar en las aplicaciones de web mapping.
La gran diferencia con el resto de estándares GIS, como GML (Geography Markup Language), es que el estándar no lo mantiene un organismo de estandarización como OGC, si no un grupo de desarrolladores expertos en web mapping y su especificación se gestiona mediante una lista de correo, desde su primera versión en 2008.
Servidores geoespaciales como GeoServer pueden devolver datos en formato GeoJson en sus servicios WFS.
Leaflet define la capa GeoJson para trabajar con este tipo de datos.
Nota: uno de los objetivos de diseño de Leaflet es la simplicidad por un lado, y realizar de forma muy eficiente las tareas mínimas necesarias por otro. Por ello, el núcleo no implementa funciones para cargar datos (GeoJSON) de servidores; debemos utilizar herramientas externas a Leaflet para ello, por ejemplo JQuery
See the Pen Leaflet GeoJSON by Xisco Guaita (@xguaita) on CodePen.
Nota: en ocasiones necesitamos localizar un conjunto de elementos sobre un mapa. La opción más sencilla es crear un fichero GeoJSON con estos elementos. Si sabemos sus coordenadas es muy fácil, únicamente necesitamos un editor de texto.
Si no sabemos las coordenadas podemos utilizar aplicaciones GIS de escritorio como QGIS o gvSIG, ambas de código abierto, o cualquiera de las opciones comerciales. Todas ellas requieren conocimientos de base en sistemas de información geográfica.
Una alternativa sencilla sin requisitos previos es geojson.io.
Toda la funcionalidad que no ofrece Leaflet por defecto la podemos encontrar en la gran cantidad de plugins de terceros que se han escrito. Una prueba más de la aceptación que ha tenido la librería estos últimos años.
Para utilizar plugins debemos descargarlos y guardarlos en un lugar accesible a nuestra aplicación web.
Veamos algunos ejemplos.
Este es uno de esos plugins que debería formar parte del núcleo de Leaflet. MiniMap define un mapa guía que muestra la posición de la vista del mapa principal.
See the Pen Leaflet MiniMap by Xisco Guaita (@xguaita) on CodePen.
El plugin Awesome-Markers define marcas de diferentes colores con iconos de ficheros de fuentes:
El ejemplo de senderismo con Awesome-Markers:
See the Pen Leaflet Awesome-Markers by Xisco Guaita (@xguaita) on CodePen.
Cuando necesitamos mostrar gran cantidad de puntos los navegadores empiezan a disminuir su rendimiento y se nota una falta de responsividad. Además, en niveles de zoom bajos (escalas pequeñas) la acumulación de puntos hace que estéticamente el mapa no resulte atractivo.
Podemos solucionar el problema mostrando los datos únicamente en escalas más grandes, donde se reducirá el número de puntos.
Pero en ocasiones nos interesará mostrar todos los puntos en todos los niveles de zoom, para ello tendremos que utilizar técnicas de agrupamiento (clustering). El plugin MarkerCluster es el mejor en esta área.
See the Pen Leaflet MarkerCluster by Xisco Guaita (@xguaita) on CodePen.
Siguiendo con el problema anterior, gran cantidad de puntos, en ocasiones nos interesará mostrarlos como mapas de calor para resaltar las zonas calientes.
Leaflet.heat es un plugin muy simple que nos permite generar heatmaps con un rendimiento muy bueno.
See the Pen Leaflet heatmap by Xisco Guaita (@xguaita) on CodePen.
La propia ESRI ha escrito un plugin para acceder a sus servicios de ArcGIS (desde la versión 10), Esri Leaflet.
Nota: actualmente está en fase de desarrollo (release candidate)
See the Pen Leaflet ESRI plugin by Xisco Guaita (@xguaita) on CodePen.
El plugin FileLayer carga al mapa ficheros KML, GPX y GeoJSON desde el almacenamiento local.
See the Pen Leaflet FileLayer by Xisco Guaita (@xguaita) on CodePen.
Aunque Leaflet implementa la funcionalidad básica de geolocalización, el plugin Leaflet.Locate define un control que simplifica las tareas de localización y seguimiento.
See the Pen Leaflet Localte by Xisco Guaita (@xguaita) on CodePen.
Leaflet.draw es un control de edición de geometrías altamente configurable:
Nota: este control únicamente edita las geometrías en el mapa, es responsabilidad del programador guardar los cambios en local (IndexedDB, WebStorage) o remoto (enviándolos a un servidor)
See the Pen Leaflet Draw by Xisco Guaita (@xguaita) on CodePen.
Otro plugin, Leaflet.StyleEditor, presenta una interfaz de usuario sencilla para editar algunas de las opciones de simbolización de los distintos tipos de geometrías.
See the Pen Leaflet Draw & StyleEditor by Xisco Guaita (@xguaita) on CodePen.