Tutorial dirigido a personas sin experiencia en programación que desean hacer uso de la biblioteca JavaScript de Leaflet para desplegar sus propios mapas.
Para seguir el tutorial solo necesitarás un ordenador, un navegador web y un editor de texto simple. Usaremos los lenguajes de programación HTML, CSS y JavaScript (JavaScript de Leaflet).
Los contenidos se estructuran en base a una serie de ejemplos prácticos que proporcionan todo el código necesario. También se incluyen unas breves explicaciones sobre cada nuevo fragmento de código introducido respecto a ejemplos anteriores. No deberías tener especiales dificultades para poder seguirlos, reproducirlos o adaptarlos a tus necesidades.
Los ejemplos propuestos podrán ampliarse o modificarse eventualmente en el futuro. Consulta el repositorio del tutorial en GitHub para más detalles.
Este primer ejemplo muestra cómo desplegar un mapa básico como el que se muestra a continuación.
Ver este ejemplo y su código fuente en una ventana independiente
Para desplegar un mapa como éste, vamos a necesitar lo siguiente:
Abre tu editor de texto y crea un documento nuevo con extensión "html". Añade al documento el siguiente código de marcado con la estructura mínima de una página web:
<!DOCTYPE html>
<html>
<head>
<title>Desplegar un mapa básico</title>
<style>
</style>
</head>
<body>
<script>
</script>
</body>
</html>
Nuestro documento HTML está vacío. Vamos a empezar a rellenarlo introduciendo las referencias a la hoja de estilos y el archivo JavaScript de Leaflet. Las referencias a estos archivos son indispensables para poder desplegar un mapa interactivo en nuestra página.
Podemos hacer uso del sitio web oficial de Leaflet para referenciar estos archivos o descargar una copia de los mismos y guardarlos en nuestro equipo para referenciarlos localmente. En este ejemplo haremos uso de los archivos alojados en el sitio web de Leaflet.
Para referenciar la hoja de estilo y el archivo JavaScript de Leaflet, introduce el siguiente código en la sección <head> del documento HTML:
<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>
Leaflet necesita que definamos un elemento <div> en nuestro documento HTML donde colocar el mapa, y que ese elemento <div> tenga una altura fija establecida. Este elemento <div> será nuestro contenedor del mapa.
Crearemos un elemento <div> y lo identificaremos como "map" para definir nuestro contenedor. Para ello, añade lo siguiente en la sección <body> del documento HTML:
<div id="map"></div>
Ahora vamos a establecer los estilos de nuestro contenedor haciendo uso del lenguaje CSS. Fijaremos su anchura en 960 píxeles y su altura en 500 píxeles. Añade lo siguiente entre las etiquetas <style> de la sección <head> del documento HTML:
#map {
width: 960px;
height: 500px;
}
Ya hemos configurado un contenedor para el mapa y hemos establecido sus estilos. Ahora vamos a escribir algo de código JavaScript para desplegar un mapa web interactivo que colocaremos en el contenedor recién definido.
La secuencia de comandos que escribiremos a continuación permite solicitar a un proveedor de teselas el juego de teselas que deseamos mostrar en nuestro mapa, así como establecer los valores iniciales del mismo.
Introduce el siguiente código JavaScript entre las etiquetas <script> del documento HTML:
<script>
var map = L.map('map').setView([36.720, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
</script>
En primer lugar, el código crea una variable 'map' a la que asigna un objeto mapa mediante la función L.map e identifica el elemento <div> que contendrá dicho mapa (en nuestro caso, el elemento <div> identificado como 'map'). Luego configura algunas opciones que sirven para ajustar el punto central y el nivel de zum iniciales del mapa.
En segundo lugar, el código crea un nuevo objeto (una capa de teselas) mediante la función L.tileLayer, especificando el juego de teselas a cargar y proporcionando la correspondiente información de atribución a través de la opción 'attribution'. En nuestro caso, hemos usado teselas de OpenStreetMap, aunque hay muchos otros proveedores de teselas libres que puedes utilizar. Prueba con un juego de teselas diferente y no olvides proporcionar siempre la correspondiente información de atribución, tanto de los datos del mapa como de las teselas de imágenes.
Por último, el código emplea el método addTo() para añadir la capa de teselas al mapa identificado por la variable 'map'.
Nuestro ejemplo ya está completo. Hemos creado un documento HTML, referenciado los archivos de Leaflet, añadido un contenedor para el mapa, definido los estilos del contenedor e inicializado el mapa. El contenido del archivo HTML definitivo debería aparecer tal que así:
<!DOCTYPE html>
<html>
<head>
<title>Desplegar un mapa básico</title>
<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>
#map {
width: 960px;
height:500px;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map = L.map('map').setView([36.720, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
</script>
</body>
</html>
Comprueba que tu código esté bien escrito, guarda el documento HTML y ábrelo con un navegador web. Deberías poder ver un mapa centrado en la ciudad de Málaga. Deslízate por él y prueba a ampliar o reducir la vista. ¡Enhorabuena! Acabas de desplegar tu primer mapa web interactivo usando la biblioteca JavaScript de Leaflet.
Este ejemplo muestra cómo desplegar un mapa básico multicapa. Un mapa básico multicapa permite seleccionar de forma interactiva el juego de teselas que deseamos mostrar en cada momento a partir de las capas de teselas disponibles.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var osmcarto = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}),
osmhumanitarian = L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
attribution: 'Datos \u00a9 <a href="http://www.openstreetmap.org">' +
'Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright">ODbL</a>) | Teselas \u00a9 <a href="https://github.com/hotosm/HDM-CartoCSS">Humanitarian HDM CartoCSS</a> (<a href="https://github.com/hotosm/HDM-CartoCSS/blob/master/LICENCE.txt" target="blanck">CC0 1.0</a>)'
}),
pnoa = L.tileLayer.wms("http://www.ign.es/wms-inspire/pnoa-ma?SERVICE=WMS&", {
layers: "OI.OrthoimageCoverage",
transparent: true,
format: 'image/jpeg',
version: '1.3.0',
attribution: 'Ortofotos <a href="http://www.scne.es/productos.html#OrtoPNOA" target="blanck">PNOA</a> \u00a9 <a href="http://www.ign.es" target="blanck">Instituto Geográfico Nacional de España</a> (<a href="https://creativecommons.org/licenses/by/4.0/legalcode.es" target="blanck">CC BY 4.0</a>)'
});
var map = L.map('map', {
center: [36.722, -4.420],
zoom: 15,
layers: [osmcarto]
});
var baseLayers = {
"Callejero (OSM)": osmcarto,
"Humanitario (OSM)": osmhumanitarian,
"Ortofotos (IGN)": pnoa
};
L.control.layers(baseLayers).addTo(map);
</script>
El código crea tres capas de teselas, 'osmcarto', 'osmhumanitarian' y 'pnoa', las dos primeras mediante la función L.tilelayer() y la tercera mediante la función L.tilelayer.wms(), que permite crear una capa de teselas a partir de un servicio WMS. Se consigna la información de atribución correspondiente a cada capa y algunas opciones adicionales facilitadas por el proveedor WMS.
Se crea un objeto mapa y se asigna al contenedor 'map', estableciendo su punto central y nivel de zum iniciales, así como la capa de teselas a mostrar de forma predeterminada, la capa 'osmcarto'. A continuación se identifican las capas base (capas mutuamente excluyentes) creando la variable 'baseLayers'. También es posible agrupar varias capas o mostrar capas superpuestas (no excluyentes): para saber más, consulta este ejemplo en la página de Leaflet.
Por último, se crea un control de capas mediante la función L.control.layers, tomando como opción la variable 'baseLayers', y se añade al mapa usando el método addTo().
Este ejemplo añade un marcador estándar a nuestro mapa básico.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.720, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var marker = L.marker([36.7204,-4.4150]).addTo(map);
</script>
El código crea una variable 'marker' a la que asigna un objeto marcador mediante la función L.marker(), que toma como valores las coordenadas geográficas del punto. El marcador se añade al mapa con el método addTo().
Ten en cuenta que puedes añadir uno o más marcadores al mapa siguiendo este mismo procedimiento. Prueba a añadir un segundo marcador creando una segunda variable 'marker2', por ejemplo, y sitúalo en otra posición del mapa para ver el resultado.
Este ejemplo añade un marcador personalizado al mapa básico. El marcador personalizado será un icono de nuestra elección.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.720, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var photoIcon = L.icon({
iconUrl: 'photo.svg',
iconSize: [38, 95],
});
var marker = L.marker([36.7204,-4.4150], {icon: photoIcon}).addTo(map);
</script>
El código crea una variable 'photoIcon' y le asigna como valor un icono mediante la función L.icon(), especificando las siguientes opciones del mismo:
La variable ‘photoIcon’ se emplea luego en la opción ‘icon’ de la función L.marker() para añadir un marcador con nuestro icono personalizado al mapa.
Este ejemplo añade al mapa básico una ventana emergente estándar vinculada a un marcador personalizado. La ventana aparece al hacer clic sobre el marcador.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.720, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var photoIcon = L.icon({
iconUrl: '../images/photo.svg'',
iconSize: [38, 95],
});
L.marker([36.7204,-4.4150], {icon: photoIcon}).bindPopup('Ayuntamiento de Málaga').addTo(map);
</script>
El código hace aparecer una ventana emergente al hacer clic sobre el marcador usando el método bindPopup(). Una alternativa al código anterior sería:
<script>
var map = L.map('map').setView([36.720, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var photoIcon = L.icon({
iconUrl: 'photo.svg',
iconSize: [38, 95],
});
var marker = L.marker([36.7204,-4.4150], {icon: photoIcon}).addTo(map);
marker.bindPopup('Ayuntamiento de Málaga');
</script>
Este ejemplo añade contenido HTML y algunos estilos adicionales a una ventana emergente vinculada a un marcador personalizado sobre un mapa básico. La ventana aparece al hacer clic sobre el marcador.
Ver este ejemplo y su código fuente en una ventana independiente
<style>
#map {
width: 960px;
height:500px;
}
.custom .leaflet-popup-tip,
.custom .leaflet-popup-content-wrapper {
background: #e60000;
color: #ffffff;
}
</style>
Este código CSS se añade a la sección <head> del archivo HTML y sirve para definir el estilo de la clase 'custom' que usaremos posteriormente en nuestro código.
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var photoIcon = L.icon({
iconUrl: 'photo.svg',
iconSize: [38, 95],
popupAnchor: [0,-15]
});
var customPopup = "<img src='../images/malaga-city-hall.jpg' alt='Ayuntamiento de Málaga' width='200px'/><br/>Ayuntamiento de Málaga. Fuente: Wikimedia Commons, imagen de Daniel Capilla (CC BY-SA 2.0).";
var customOptions = {
'maxWidth': '200',
'className' : 'custom'
}
var marker = L.marker([36.7204,-4.4150], {icon: photoIcon}).bindPopup(customPopup, customOptions).addTo(map);
</script>
En primer lugar, el código añade una opción 'popupAnchor' al icono. Esta opción permite establecer unos valores relativos de desplazamiento de la ventana emergente respecto del punto en el que se encuentra el marcador de manera tal que el icono del marcador resulte más visible.
Luego se crea la variable ‘customPopup’ y se le asigna algo de contenido HTML.
A continuación se crea la variable ‘customOptions’ y se configuran unas cuantas opciones, como el ancho máximo de la ventana emergente ('maxWidth') y sus estilos, asignando el nombre de clase 'custom' para que se apliquen a la ventana los estilos CSS personalizados de esa clase.
Ten en cuenta que el ancho máximo predeterminado de una ventana emergente es de 300 píxeles. Si el contenido de tu ventana emergente desborda ese ancho, asegúrate de asignarle un valor adecuado cambiando la opción 'maxWidth' para adaptar el ancho al contenido.
Finalmente, el código emplea el método bindPopup para vincular la ventana emergente al marcador, tomando como argumentos el contenido HTML y las opciones antes definidas. También las variables creadas previamente se consignan según este método.
Los siguientes ejemplos muestran como añadir algunas formas geométricas al mapa básico. Aprenderemos a añadir un círculo, un rectángulo, un polígono y una polilínea.
Este ejemplo añade al mapa básico un círculo a partir de su centro y su radio.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
L.circle([36.722, -4.420], 300,{color:'blue', opacity:1, fillColor: 'blue', fillOpacity:.4}).addTo(map);
</script>
El código hace uso de la función L.circle() para crear un círculo a partir de su centro y su radio, además de ajustar otras opciones de estilo, como el color del borde, el color de relleno o sus respectivas opacidades. El círculo se añade al mapa usando el método addTo().
Este ejemplo añade al mapa básico un rectángulo a partir de dos de sus vértices.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var bounds = [[36.725, -4.425], [36.720, -4.415]];
L.rectangle(bounds, {color: "purple", weight: 2}).addTo(map);
</script>
El código define una variable 'bounds' con los puntos que delimitan las dimensiones del rectángulo, sus vértices superior izquierdo e inferior derecho. El código hace uso de la función L.rectangle() para crear el rectángulo y ajusta además otras opciones de estilo, como el color del mismo o el ancho de su borde. Finalmente, lo añade al mapa usando el método addTo().
Este ejemplo añade al mapa básico un polígno a partir de la posición de sus vértices.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var area = [[36.728, -4.425],[36.718, -4.425],[36.722, -4.415]];
L.polygon(area,{color:'green',opacity:.6}).addTo(map);
</script>
El código define una variable 'area' con los vértices del polígono. Esta variable se utiliza después en la función L.polygon() para crear el polígono, ajustando además otras opciones de estilo, como el color del mismo o su opacidad. El polígono se añade al mapa usando el método addTo().
Este ejemplo añade al mapa básico una polilínea a partir de los puntos que definen su trazado.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var track = [[36.7205, -4.4130],[36.7165, -4.4260],[36.7218, -4.4250],[36.7230, -4.4240],[36.7240, -4.4220],[36.7250, -4.4220],[36.7270, -4.4240],[36.7270, -4.4250],[36.7270, -4.4270],[36.7280, -4.4300]];
L.polyline(track,{color:'red',opacity:1}).addTo(map);
</script>
El código define una variable 'track' con los puntos que determinan el trazado de la polilínea. Esta variable se utiliza después en la función L.polyline() para crear la polilínea, ajustando además otras opciones de estilo, como el color de la misma o su opacidad. La polilínea se añade al mapa usando el método addTo().
Este ejemplo despliega un mapa básico que muestra una capa de datos GeoJSON codificados como una variable.
Ver este ejemplo y su código fuente en una ventana independiente
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var historic_features = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-4.42428,36.71802],
[-4.42352,36.71829],
[-4.42388,36.71878],
[-4.42461,36.71845]
]]
},
"properties": {
"Nombre": "Mercado de Atarazanas",
"Descripción": "Mercado municipal central"
}
},{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-4.41942,
36.72007
]
},
"properties":{
"Nombre": "Catedral de Málaga",
"Descripción": "Principal templo cristiano de la ciudad"
}
},{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-4.42515, 36.72056],
[-4.42506, 36.72081],
[-4.42512, 36.72144],
[-4.42409, 36.72291],
[-4.42345, 36.72343],
[-4.42076, 36.72437]
]
},
"properties": {
"Nombre": "Calle Carretería",
"Descripción": "Calle del Centro Histórico"
}
},{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-4.41569,
36.72132
]
},
"properties": {
"Nombre": "Alcazaba",
"Descripción": "Fortificación palaciega medieval"
}
}]
};
L.geoJson(historic_features, {
onEachFeature: function(feature,layer) {
layer.bindPopup(feature.properties.Nombre);
}
}).addTo(map)
</script>
El código define una variable 'historic_features' que contiene el conjunto de datos GeoJSON. La capa de datos se crea a través de una instancia de la clase L.geoJson(), que toma la variable 'historic_features' como parámetro y la añade al mapa usando el método addTo().
La opción 'onEachFeature' de la capa de datos es opcional. Se usa para enlazar una ventana emergente a cada característica para que muestre el valor de una propiedad, en el ejemplo, la propiedad 'Nombre'. Se puede seleccionar cualquiera de las propiedades de una característica incluida en el conjunto de datos mediante 'feature.properties.nombre-de-la-propiedad'.
Aunque es habitual que un archivo GeoJSON contenga solo un tipo de elemento geográfico (puntos, líneas o polígonos), esto no es un requisito. Se pueden introducir datos GeoJSON con múltiples geometrías y datos descriptivos asociados a ellas en el código fuente.
Para mostrar datos con diferentes geometrías, será necesario especificar el tipo de geometría y las coordenadas apropiadas de cada elemento. Una cadena lineal debe incluir al menos dos puntos. Los polígonos no necesitan cerrarse sobre sí mismos, es decir, no es necesario incluir las coordenadas del punto inicial al final de la lista de coordenadas.
Este ejemplo despliega un mapa básico que muestra una capa de datos a partir de un archivo GeoJSON externo. Aunque en este ejemplo emplearemos un archivo GeoJSON con un único tipo de geometría (puntos), esto no es un requisito. Se puede trabajar con archivos GeoJSON que incluyan múltiples geometrías (puntos, líneas o polígonos).
Ver este ejemplo y su código fuente en una ventana independiente
Los datos se encuentran inicialmente en forma de un archivo GeoJSON de nombre 'bicycle-parkings.geojson'. El archivo contiene información relativa a la ubicación de los estacionamientos de bicicleta disponibles en Málaga.
Para importar estos datos al mapa, tendremos que codificarlos como una variable (en nuestro caso, la variable 'data'). Para hacer esto, abrimos el archivo GeoJSON con un editor de texto simple e incluimos lo siguiente como primera línea del archivo:
var data =
A continuación, referenciamos el archivo de datos en nuestro documento HTML introduciendo el siguiente código en la sección <head> del documento:
<script src="bicycle-parkings.geojson"></script>
Este archivo podría añadirse al mapa directamente como una capa de datos a través de una instancia de la clase L.geoJson(), que toma la variable 'data' como parámetro y la añade al mapa usando el método addTo(). El resultado puede verse aquí.
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
L.geoJson(data).addTo(map);
</script>
No obstante, en este ejemplo no añadiremos los datos directamente al mapa. El inconveniente de cargar así los datos es que, cuando nuestra capa de datos incluye gran número de puntos o marcadores, estos se superpongan unos con otros. La usabilidad del mapa en ese caso se verá notablemente afectada, ya que cuando hay muchos puntos juntos, resulta casi imposible saber en qué marcador particular estamos haciendo clic.
Para resolver el problema de la superposición, emplearemos la agrupación de marcadores, un mecanismo mediante el cual los puntos cercanos se agrupan bajo un único marcador que incluye además un indicador con la cantidad de puntos agrupados. Esta funcionalidad no está incluida en la biblioteca de Leaflet de forma predeterminada, debemos incorporarla mediante una extensión externa.
En este ejemplo emplearemos la extensión Leaflet.markercluster. Esta extensión se encarga de averiguar las agrupaciones de marcadores, mostrarlas y separarlas a medida que se hace zum sobre el mapa (este ejemplo muestra solo una implementación sencilla de esta extensión; hay muchas opciones que puedes explorar).
Para usar la funcionalidad de agrupación de marcadores, tendremos que incluir en nuestro documentos HTML las referencias a las hojas de estilos y el archivo JavaScript de la extensión. Estos archivos se pueden descargar y usar localmente, aunque en este ejemplo emplearemos los archivos alojados en el sitio web oficial de la extensión.
Para referenciar estos archivos, introduce el siguiente código en la sección <head> del documento HTML (nótese que el código también hace referencia al archivo de datos 'bicycle-parkings.geojson', que vamos a necesitar):
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.0/dist/MarkerCluster.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.0/dist/MarkerCluster.Default.css" />
<script src="https://unpkg.com/leaflet.markercluster@1.4.0/dist/leaflet.markercluster.js"></script>
<script src="bicycle-parkings.geojson"></script>
A continuación, introduce el siguiente código JavaScript entre las etiquetas <script> del documento HTML:
<script>
var map = L.map('map').setView([36.722, -4.420], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Datos © <a href="http://osm.org/copyright" target="blanck">Colaboradores de OpenStreetMap</a> (<a href="http://www.openstreetmap.org/copyright" target="blanck">ODbL</a>) | Teselas <a href="https://github.com/gravitystorm/openstreetmap-carto" target="blanck">OSM Carto</a> © Randy Allan y otros colaboradores (<a href="https://creativecommons.org/licenses/by-sa/2.0/deed.es" target="blanck">CC BY-SA 2.0</a>)'
}).addTo(map);
var parkingIcon = L.icon({
iconUrl: 'bicycle-parking.svg',
iconSize: [20,20]
});;
var parkings = L.geoJson(data, {
pointToLayer: function(feature,latlng){
var marker = L.marker(latlng,{icon: parkingIcon});
marker.bindPopup("Capacidad: " + feature.properties.capacity);
return marker;
}});
var clusters = L.markerClusterGroup({ showCoverageOnHover: false });
clusters.addLayer(parkings);
map.addLayer(clusters);
</script>
En primer lugar, después de inicializar el mapa, el código define un icono personalizado para los marcadores identificado con la variable 'parkingIcon'. Para más detalles sobre cómo establecer un icono personalizado, consulta el ejemplo Añadir un marcador personalizado.
Luego, define una variable 'parkings' a la que le asigna la capa de datos GeoJSON. La capa de datos se crea a través de una instancia de la clase L.geoJson(). La función pointToLayer de Leaflet es usa aquí para determinar cómo convertir una característica de punto a una capa del mapa. Esta función siempre acepta dos argumentos: la característica GeoJSON y un objeto LatLng que representa su ubicación (no es necesario indicarla, Leaflet la calculará automáticamente). La función devuelve una variable 'marker' a la que asigna un objeto marcador mediante la función L.marker(), que toma como valores las coordenadas geográficas del punto y usa como imagen del marcador nuestro icono personalizado.
Antes de devolver el marcador como resultado de resolver la función pointToLayer, el código crea una ventana emergente usando el método bindPopup(). Tan solo es necesario indicar el contenido que debe aparecer en la ventana emergente en forma de código HTML. En nuestro ejemplo, la ventana mostrará información relativa a la capacidad de cada estacionamiento de bicicletas al hacer clic sobre un marcador. Este dato corresponde con la propiedad 'capacity' incluida en nuestro archivo de datos GeoJSON. Se puede seleccionar cualquiera de las propiedades de una característica incluida en el conjunto de datos mediante 'feature.properties.nombre-de-la-propiedad'.
Finalmente, el código crea una capa de marcadores agrupados con Leaflet.markercluster, una función que forma parte de la extensión, asignándole la variable 'clusters'. Esta capa es una agrupación de marcadores a la que podemos añadir marcadores individuales que luego serán agrupados. El parámetro 'showCoverageOnHover' sirve para indicar si queremos que al pasar el ratón por encima de un grupo de marcadores se muestre la extensión real que ocupan sus marcadores. Su valor predeterminado es 'true'. Por último, la capa 'clusters' se añade al mapa con addLayer.