Si hace un par de semanas veíamos cómo añadir un servicios WFS desde OpenLayers, en este artículo vamos a mostrarte cómo acceder a servicios WFS desde el cliente de mapas web Leaflet.
Añadiremos nuestra capa vectorial countries en Leaflet que tenemos almacenada en el servidor espacial GeoServer como un servicio WFS.
Una vez que tenemos un sencillo visor web creado con Leaflet, vamos a añadir ahora una capa superpuesta de tipo vector.
En Leaflet las capas vectoriales se pueden representar mediante la clase L.GeoJSON. Hemos visto cómo hacerlo en el post Cómo crear un mapa web en Leaflet a partir de un GeoJSON.
Sin embargo Leaflet no es capaz de leer los archivos JSON que devuelve la petición GetFeature de WFS.
Es decir, utilizar directamente la url que devuelve GeoServer no es posible, Leaflet solo soporta la extensión .js, cualquier otra extensión da error de «formato no soportado».
Hay dos opciones para añadir una servicio WFS en Leaflet:
- Utilizando AJAX y jQuery.
- Utilizando un plugin de Leaflet (por ejemplo Leaflet-WFST).
Añadiendo una capa WFS y recuperando su información utilizando AJAX
En primer lugar añadiremos al script la librería jQuery:
<script src="https://code.jquery.com/jquery-3.2.1.js" ></script>
JQuery es una librería de JavaScript de código abierto, que simplifica la tarea de programar en JavaScript y permite agregar interactividad a un sitio web sin tener conocimientos del lenguaje.
Vamos a construir la URL con el servicio WFS de GeoServer donde debemos reanudar nuestro geoJSON.
<script> var map = L.map('map').setView([0, 0], 4); var owsrootUrl = 'http://localhost:8080/geoserver/ows'; var defaultParameters = { service: 'WFS', version: '1.0.0', request: 'GetFeature', typeName: 'earth:countries', outputFormat: 'application/json' }; var parameters = L.Util.extend(defaultParameters); var URL = owsrootUrl + L.Util.getParamString(parameters);
La dirección URL servirá para crear la llamada AJAX a la página que contiene nuestro GeoJSON.
La llamada AJAX se construye mediante JQuery, a través de la cual se pasa la URL y una función de éxito, o qué efecto debe realizarse la llamada.
AJAX (JavaScript Asíncrono y XML) nos proporciona la posibilidad de hacer peticiones al servidor (intercambiar datos) sin tener que volver a cargar la página.
En nuestro ejemplo, vamos a hacer clic sobre los objetos geográficos de la capa countries, y mostraremos un popup que contiene la información captada por GeoJSON. En ese caso, veremos el nombre del país.
El método $.ajax () Realiza una solicitud asíncrona AJAX
$.ajax({ url: URL, success: function (data) { var geojson = new L.geoJson(data, { style: {"color":"#2ECCFA","weight":2}, onEachFeature: function(feature, layer){ layer.bindPopup("Has hecho click en " + feature.properties.name); }} ).addTo(map); } }); </script>
Código completo:
<!DOCTYPE html> <html> <meta charset="utf-8" /> <head> <script src=" https://unpkg.com/leaflet@1.2.0/dist/leaflet.js "></script> <link rel="stylesheet" href=" https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" /> <script src="https://code.jquery.com/jquery-3.2.1.js" ></script> <style> #map { width: 100%; height: 600px; box-shadow: 5px 5px 5px #888; } </style> </head> <body> <div id="map"></div> <script> var map = L.map('map').setView([0, 0], 2); var owsrootUrl = 'http://localhost:8080/geoserver/ows'; var defaultParameters = { service: 'WFS', version: '1.0.0', request: 'GetFeature', typeName: 'earth:countries', outputFormat: 'application/json', }; var parameters = L.Util.extend(defaultParameters); var URL = owsrootUrl + L.Util.getParamString(parameters); $.ajax({ url: URL, success: function (data) { var geojson = new L.geoJson(data, { style: {"color":"#2ECCFA","weight":2}, onEachFeature: function(feature, layer){ layer.bindPopup("Has hecho click en " + feature.properties.name); }} ).addTo(map); } }); </script> </body> </html>
El plugin Leaflet-WFST
Este plugin permite acceder al protocolo WFS-T de la OGC.
1. Ve a la página de plugins de Leaflet: http://leafletjs.com/plugins.html
2. En la Sección: Overlay data > Overlay data formats y pincha sobre Leaflet-WFST. Este es el plugin para añadir las capas WFS en Leaflet:
3. A continuación nos descargamos el plugin haciendo clic sobre el botón Download ZIP:
4. Descomprimimos el archivo y lo colocamos en el directorio en el que se encuentre nuestro HTML.
5. En la cabecera del HTML añadimos la librería JavaScript Leaflet-WFST.src.js debajo de la librería JS y CSS de Leaflet:
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" /> <script src="Leaflet-WFST-master/dist/Leaflet-WFST.src.js"></script>
Ahora ya podemos utilizar la nueva clase L.WFS. Este plugin implementa la clase L.WFS con las siguientes opciones:
Nombre de la opción | Valor por defecto | Descripción |
---|---|---|
crs | L.CRS.EPSG3857 | Sistema de Referencia Espacial para la capa, debería implementar ICRS, por ejemplo Proj4Leaflet |
showExisting | true | Carga de los objetos espaciales en el momento de creación de la capa |
geometryField | ‘Shape’ | Campo que almacena las geometrías, para servicios no transaccionales este valor puede omitirse. |
url | – | url del servicio WFS, por ejemplo: http://demo.opengeo.org/geoserver/osm/ows |
typeNS | – | Nombre del espacio de trabajo |
typeName | – | Nombre de la capa |
style | – | Estilo de la capa vectorial |
Afortunadamente la propiedad style que sirve para definir nuestro propio estilo, está incluida como opción.
Sin embargo la propiedad onEachFeature no lo está 🙁 , por lo que no es posible conseguir lanzar un popup al hacer clic sobre un elemento.
Ejemplo básico de visualización un servicio WFS en Leaflet
var map = L.map('map').setView([0, 0], 2);
var boundaries = new L.WFS({
url: 'http://demo.boundless.org/geoserver/ows',
typeNS: 'topp',
typeName: 'tasmania_state_boundaries',
crs: L.CRS.EPSG4326,
style: {
color: 'blue',
weight: 2
}
}).addTo(map)
.on('load', function () {
map.fitBounds(boundaries);
})
Ahora modificamos los datos del ejemplo para añadir una capa de nuestro servidor GeoServer:
var map = L.map('map').setView([0, 0], 2); var boundaries = new L.WFS({ url: 'http://localhost:8080/geoserver/earth/ows?', typeNS: 'earth', typeName: 'countries', crs: L.CRS.EPSG4326, style: { 'color': "#e12a2a", 'fill' : false, 'dashArray': "5, 5", 'weight': 2, 'opacity': 0.6 } }, new L.Format.GeoJSON({crs: L.CRS.EPSG4326})) .addTo(map);
Aquí vemos el resultado de la capa countries añadida como servicio WFS en Leaflet con la simbología que hemos definido (color de trazo rojo discontinuo y sin relleno):
Este plugin también nos permite realizar edición de las capas vectoriales a través de la clase L.WFST. Para ello es necesario hacer uso de los plugins Leaflet.Editable y Leaflet.EasyButton.
En este ejemplo (Polygons) vemos una demo para leer, escribir y guardar la edición de datos vectoriales utilizando el formato GeoJSON, el código empleado lo podemos ver en el repositorio de github: https://github.com/Flexberry/Leaflet-WFST/blob/master/examples/polygonGeoJSON.html
Licenciado en Geografía. Máster en Sistemas de Información Geográfica. Consultor GIS desde el año 2004. En MappingGIS desde el año 2012 para ayudarte a impulsar tu perfil GIS y diferenciarte de la competencia. Echa un vistazo a todos nuestros cursos de SIG online.
Hola Aurelio,
Do you have any advice on how I can get a pop-up window to work with this? And to display the layer properties?
Gracias,
Clara
Hello Clara,
I don´t know how to do that in a WFS service, however you can use the getfeatureinfo request in a WMS service: http://openlayers.org/en/latest/examples/getfeatureinfo-tile.html? Regards!
Hola, necesito una ayuda porque no consigo que me funcione.
Tengo un visor leaflet y quiero mostrar una capa que tengo en el geoserver. Ya descargue el pluguin y he seguido todos los pasos.
Para probar el funcionamiento queria mostrar una capa que viene por defecto al instalar el opengeo suite.
La capa esta en c:ProgramData/Boundless/Opengeo/geoserver/workspaces/usa/states
En leaflet he introducido lo siguiente:
var boundaries = new L.WFS({
url: ‘http://localhost:8080/geoserver/usa/ows?’,
typeNS: ‘usa’,
typeName: ‘states’,
crs: L.CRS.EPSG4326,
style: {
‘color’: «#e12a2a»,
‘fill’ : false,
‘dashArray’: «5, 5»,
‘weight’: 2,
‘opacity’: 0.6
}
}, new L.Format.GeoJSON({crs: L.CRS.EPSG4326}))
.addTo(map);
En typeNS he puesto el nombre del espacio de trabajo, y en el typename el nombre de la capa
Supongo que no me aparece la capa o porque la dirección que pongo no es correcta o bien porque la capa del geoserver no esta preparada para cargarla como wms.
te agradeceria me echaras una mano
muchas gracias
Hola Jose,
Lo he probado y funciona perfectamente. GeoServer siempre crea los servicios WMS y WFS por defecto para todas las capas.
Asegúrate de incluir dentro del script la creación del mapa:
var map = L.map(‘map’).setView([0, 0], 2);
y tener el html en el mismo directorio que la carpeta del plugin.
Si no te funciona utiliza el depurador Firebug de firefox para encontrar la línea en la que se está produciendo el error.
Saludos!
Hola, he hecho la corrección que me has dicho, pero en el firebug me aparece el siguiente error:
Solicitud desde otro origen bloqueada: la política de mismo origen impide leer el recurso remoto en http://localhost:8080/geoserver/opengeo/ows?& (razón: falta la cabecera CORS ‘Access-Control-Allow-Origin’
Que puedo hacer?
Hola,
Debes ejecutar el visor desde el servidor web: http://localhost:8080/geoserver/www/web_wfs.html Aquí tienes más información sobre el control de acceso HTTP (CORS): https://developer.mozilla.org/es/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Origin Saludos!
Muchas gracias Aurelio. Problema resuelto, lo estaba ejecutando desde otro localhost.
Opengeo lo tengo en el localhost 8080, pero leaflet lo tenia en otro localhost que cree con apache hace tiempo.
Lo he pasado al directorio www y funciona correctamente.
Un saludo
Hola Aurelio,
este formato funciona igual que el wms donde se reflejan las modificaciones de mi archivo desde QGIS
Hola Daniel,
El estándar WFS es un servicio para acceder a los datos vectoriales. El estándar WMS es un servicio para visualizar datos, por lo que el uso de uno y otro es muy diferente.
Sin embargo las actualizaciones realizadas en el servidor se reflejan inmediatamente en todos los servicios implementados.
Saludos!