Aunque Leaflet es una librería de mapas muy versátil, por el momento carece de funciones nativas para cargar datos vectoriales remotos, como por ejemplo servicios WFS. En parte, esto es debido a la filosofía de la propia API, ofrecer de un conjunto de funcionalidades básicas con el mejor soporte posible. Esto, unido al gran número de plugins disponibles para Leaflet, consigue dotar de muchas de las funciones que no están incorporadas nativamente. Nuestro caso actual no es una excepción, pues existen varios plugins que permiten obtener datos vectoriales dinámicamente para usarlos en nuestros mapas (por ejemplo, el plugin leaflet-ajax).
Si por alguna razón estos plugins no satisfacen nuestras necesidades, o bien no queremos usarlos, es posible desarrollar muy fácilmente nuestro propio código para manejar las peticiones de datos vectoriales. Una vez obtenido el conjunto de datos, estará a nuestra disposición para procesarlo como más convenga.
En el siguiente ejemplo se trabajará con los datos del servicio geológico de Estados Unidos sobre los últimos terremotos registrados a escala mundial. En su página Web ofrecen una serie de datasets en formato GeoJSON, que obtendremos para usarlos en nuestro visor Leaflet. Partiremos de un mapa simple con una capa base de OpenStreetMap:
... <script type="text/javascript"> var mapa = L.map("mapa", { center: [20, 0], zoom: 3 }); var capaOSM = L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"); capaOSM.addTo(mapa); </script> ...
Para obtener los datos vectoriales, crearemos una función que tome como parámetro la URL del servicio y devuelva los datos como respuesta. Dado que una petición a un servidor tarda mucho más tiempo en llevarse a cabo que la ejecución normal del resto del código, es necesario trabajar de forma asíncrona. De este modo, la carga de los datos vectoriales se realizará solamente cuando estén disponibles.
En la función utilizaremos el objeto Promise, que permite gestionar las llamadas AJAX muy fácilmente:
function peticionAjax(url) { return new Promise( function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open("get", url); xhr.onload = function () { if (xhr.status === 200) { resolve(xhr.response); } else { reject(Error(xhr.statusText)); } }; xhr.onerror = function () { reject(Error('Error de red')); };; xhr.send(); } ); }
La función peticionAjax utiliza como argumento la URL del servicio, y devuelve una Promise que ejecutará el método resolve() en caso de éxito en la petición, y el método reject() en caso de rechazo del servidor o de cualquier otro error.
Para usar nuestra función peticionAjax, la invocaremos suministrando la URL y manejando los resultados con then() y catch(), en función de si la Promise es aceptada o rechazada, respectivamente:
var urlTerremotos = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_month.geojson"; peticionAjax(urlTerremotos) .then(function (respuesta) { var datos = JSON.parse(respuesta); var capaVectorial = L.geoJSON(datos); capaVectorial.addTo(mapa); }) .catch(function (respuesta) { alert(respuesta); });
Mediante esta función, la capa vectorial solo se crea y se carga si el resultado de la petición es exitoso. En la función ejecutada dentro de then() se puede incluir todo el procesamiento que consideremos conveniente, ya que aquí tenemos un control total de los datos vectoriales. Por ejemplo, se puede cambiar la simbología o añadir un popup:
peticionAjax(urlTerremotos) .then(function (respuesta) { var datos = JSON.parse(respuesta); var capaVectorial = L.geoJSON(datos, { pointToLayer: function (entidad, latlng) { return L.circleMarker(latlng); } }); capaVectorial.bindPopup(function (layer) { var fecha = 'Fecha: ' + new Date(layer.feature.properties.time).toLocaleString(); var magnitud = 'Magnitud: ' + layer.feature.properties.mag; return '<div>' + fecha + '<br>' + magnitud + '</div>'; }); capaVectorial.addTo(mapa); }) .catch(function (respuesta) { alert(respuesta); });
Ahora, la capa de marcadores con la ubicación de los terremotos cambia su simbología a elementos circulares, más agradables para un mapa de este tipo. Utilizar los atributos de las entidades en la capa vectorial permite ir mucho más allá con la simbología, cómo cambiar tamaños, colores o formas. El popup implementado muestra la fecha y la magnitud de cada terremoto, aprovechando también los atributos de la capa. Es resultado es el siguiente:
Como vemos, prescindir del uso de plugins nos otorga una mayor flexibilidad, aunque a cambio de un incremento en la complejidad de nuestro código. Sin embargo, el ejemplo mostrado no es especialmente complicado y nos da la oportunidad de controlar totalmente lo que sucede cuando se obtiene la capa vectorial.
Deja tu comentario