Esri Leaflet: herramientas para usar servicios de ArcGIS con Leaflet

Esri (Environmental Systems Research Institute) es una de las principales empresas del sector GIS siendo mundialmente conocida por haber desarrollado el formato shapefile y la plataforma ArcGIS. Pero Esri, además ofrece muchos otros servicios. Podemos visualizar algunos de sus mapas mediante librerías JavaScript utilizando ESRI Leaflet.

ESRI Leaflet es un conjunto de herramientas para usar los servicios de ArcGIS con Leaflet. En la web encontraremos muchos ejemplos, documentación, plugins, etc. Conviene leer los términos de uso para esta aplicación.

El catálogo de ejemplos y de posibilidades que permite ESRI Leaflet no caben en el espacio limitado de este blog, por lo que nos centraremos en una de sus capacidades más interesantes. Nos referimos a la posibilidad de realizar consultas de tipo query a los datos del mapa. Veamos cómo se hace.

Esri Leaflet

Mapas base de Esri

El primer paso es cargar las librerías de leaflet y de Esri-Leaflet, esto lo hacemos mediante los correspondientes enlaces al CDN.

  <!-- Cargamos Leaflet desde CDN-->
  <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>  

  <!-- Cargamos Esri Leaflet desde CDN -->
  <script src="https://unpkg.com/esri-leaflet@2.2.3/dist/esri-leaflet.js"
    integrity="sha512-YZ6b5bXRVwipfqul5krehD9qlbJzc6KOGXYsDjU9HHXW2gK57xmWl2gU6nAegiErAqFXhygKIsWPKbjLPXVb2g=="
    crossorigin=""></script>   

Esri nos proporciona un interesante catálogo de mapas base tanto en formato raster como vectoriales. La lista de mapas disponibles es la siguiente, aunque no todas ofrecen servicio para todos los lugares y niveles de zoom:

  • Streets
  • Topographic
  • NationalGeographic
  • Oceans
  • Gray
  • DarkGray
  • Imagery
  • ImageryClarity
  • ImageryFirefly
  • ShadedRelief
  • Terrain
  • USATopo
  • Physical

Solo necesitamos crear una instancia a L.esri.basemapLayer, tal y como se indica a continuación, indicando el nombre del mapa que queremos visualizar. En este ejemplo ‘NationalGeographic’.

<body>
    <div id="map"></div>
    <script>
        var map = L.map('map').setView([40.965, -5.664], 14);

        L.esri.basemapLayer('NationalGeographic').addTo(map);

    </script>

Nota: Para mostrar un servicio de ArcGIS Online en cualquier aplicación de Leaflet, hay que incorporar la atribución de Esri según se indica en los términos de uso.

FeatureLayers

L.esri.FeatureLayer se usa para visualizar, diseñar, consultar y editar datos geográficos vectoriales alojados en ArcGIS Online y publicados con ArcGIS Server. El texto de copyright del servicio se agrega al mapa de atribución automáticamente. En ArcGIS REST Services Directory podemos ver algunas capas disponibles. En este ejemplo utilizaremos una capa con la localización de los aeropuertos llamada Airport_2.

var airports = L.esri.featureLayer({
  url:'https://services.arcgis.com/rOo16HdIMeOBI4Mb/ArcGIS/rest/services/Airports_2/FeatureServer/0'
}).addTo(map);

El código anterior crea un marcador en las posiciones de los aeropuertos. Podemos personalizar el estilo del marcador utilizando alguna de la opciones de L.esri.featureLayer, como pointToLayer.

  var airports = L.esri.featureLayer({
    url: 'https://services.arcgis.com/rOo16HdIMeOBI4Mb/ArcGIS/rest/services/Airports_2/FeatureServer/0',
    pointToLayer: function (geojson, latlng) {
      return L.circleMarker(latlng);
    },
    style:{
      color: '#5B7CBA',
      weight: 2,
      opacity: 0.85,
      fillOpacity: 0.5
    }
  }).addTo(map);

Añadiendo un popup

Es interesante que los datos de cada elemento puedan ser consultados. En el caso de la capa de aeropuertos podemos consultar los campos que contiene la tabla de datos en https://services.arcgis.com/rOo16HdIMeOBI4Mb/ArcGIS/rest/services/Airports_2/FeatureServer/0

Para realizar la consulta creamos un popup que nos muestre los datos, de la siguiente forma:

  airports.bindPopup(function (layer) {
    return L.Util.template('<p>FID: {FID}<br>SCALERANK: {scalerank}<br>NOMBRE: {name}<br>TYPE: {type}<br>LOCATION: {location}</p>', layer.feature.properties);
  });

El mapa obtenido es el siguiente:

L.esri.Query

Una vez que hemos construido el mapa, podemos abordar el objeto principal de este artículo. La consulta y selección de los datos contenidos en una featureLayer. Publicar un mapa en la web con nuestros datos es algo muy sencillo. Leaflet, por ejemplo nos permite hacerlo de forma muy eficiente, y es muy fácil de aprender. Pero la clave para hacer mapas más interesantes está en la interacción con el usuario, siendo la consulta y filtrado de datos un elemento esencial.

L.esri.Query proporciona una API personalizable para construir parámetros de solicitud y ejecutar consultas sobre el mapa.

Métodos

L.esri.Query dispone de muchos métodos algunos de los cuales son los siguientes:

  • within, contains, intersects, bboxIntersects, overlap: Selecciona los datos de la capa en relación con una geometría. Es decir podemos seleccionar los datos contenidos en un rectágulo con within. En el caso de intersects se mostrarían todos los objetos que están en contacto con el rectángulo.
  • nearby. Sirve para consultar los datos incluidos en una distancia definida en metros alrededor de un punto(latlng)
  • where.  Agrega una cláusula where a la consulta. Los valores de cadena deben indicarse con comillas simples, es decir: query.where(«FIELDNAME = ‘field value'»)
  • limit: Limita el número de resultados devueltos por esta consulta.
  • between: Consulta las features dentro de un rango de tiempo dado. Solo disponible para Capas y/o Servicios con timeInfo en sus metadatos.

Otros métodos

  • fields: Una matriz de campos asociados para solicitar para cada característica.
  • returnGeometry: Regresar geometría con resultados. El valor predeterminado es true .
  • simplify: Simplifica las geometrías de las entidades de salida para la vista de mapa actual.
  • orderBy:Ordena las características de salida utilizando valores de un campo individual.
  • featureIds: Devuelve solo ID de las capas específicas si coinciden con otros parámetros de consulta.
  • precision: Devuelve solo estos muchos puntos decimales de precisión en las geometrías de salida.
  • distinct(): Asegura que no se devolverán valores de campo duplicados o geometría en la solicitud posterior.
  • run: Ejecuta la solicitud de consulta con los parámetros actuales
  • count: Ejecuta la solicitud de consulta con los parámetros actuales, pasando solo el número de entidades que coinciden con la consulta para devolver la llamada como un Integer .
  • ids: Ejecuta la solicitud de consulta con los parámetros actuales, pasando solo una matriz de ids de características que coinciden con la consulta para devolver la callback .

Veamos un ejemplo para realizar una consulta de distancia.

Utilizaremos el método nearby para seleccionar aquellos aeropuertos que se encuentren a una distancia dada de otro aeropuerto. Para hacerlo realizamos una consulta query sobre la capa airports de la siguiente forma: airports.query() y a continuación escribimos el método nearby, que tomará las coordenadas del aeropuerto seleccionado (e.latlng, 500000) indicando la distancia en m. En esta ocasión queremos ver los aeropuertos que están a una distancia de 500 km.

 var previousIds = [];

  map.on('click', function(e){
    airports.query().nearby(e.latlng, 500000).where("type='major'").ids(function(error, ids){
      for (var j = 0; j < previousIds.length; j++) {
        airports.resetStyle(previousIds[j]);
      }

      previousIds = ids;

      for (var i = 0; i < ids.length; i++) {
        airports.setFeatureStyle(ids[i], {
          color: '#BA454E',
          weight: 2,
          opacity: 0.85,
          fillOpacity: 0.5
        });
      }
    });
  });

Con el código anterior  cuando hacemos clic sobre un marcador, estamos realizando una consulta de los aeropuertos que están a una distancia de 500 km, pero además hemos introducido una condición. Queremos que los aeropuertos seleccionados sean además de un tipo concreto type=’major‘. Además utilizamos el método ids para que nos devuelva solo los datos de la consulta actual. Al resultado de la consulta le aplicamos un nuevo estilo ( setFeatureStyle) para poder visualizarlo en la pantalla.

Puedes ver su funcionamiento en le siguiente mapa. Haz clic sobre uno de los aeropuertos y mostrará el resultado de la consulta cambiando el estilo de los marcadores seleccionados.

Código del ejemplo

El código al completo es:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Esri Leaflet Map </title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />

  <!-- Cargamos Leaflet desde CDN-->
  <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>  

  <!-- Cargamos Esri Leaflet desde CDN -->
  <script src="https://unpkg.com/esri-leaflet@2.2.3/dist/esri-leaflet.js"
    integrity="sha512-YZ6b5bXRVwipfqul5krehD9qlbJzc6KOGXYsDjU9HHXW2gK57xmWl2gU6nAegiErAqFXhygKIsWPKbjLPXVb2g=="
    crossorigin=""></script>   

  <style>

    html,
    body,
    #map {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
    }

  </style>

</head>
<body>

<div id="map"></div>

<script>
  var map = L.map('map').setView([40.965, -5.664], 4);

  L.esri.basemapLayer('Streets').addTo(map);
  var airports = L.esri.featureLayer({
    url: 'https://services.arcgis.com/rOo16HdIMeOBI4Mb/ArcGIS/rest/services/Airports_2/FeatureServer/0',
    pointToLayer: function (geojson, latlng) {
      return L.circleMarker(latlng);
    },
    style:{
      color: '#5B7CBA',
      weight: 2,
      opacity: 0.85,
      fillOpacity: 0.5
    }
  }).addTo(map);

  var previousIds = [];

  map.on('click', function(e){
    airports.query().nearby(e.latlng, 500000).where("type='major'").ids(function(error, ids){
      for (var j = 0; j < previousIds.length; j++) {
        airports.resetStyle(previousIds[j]);
      }

      previousIds = ids;

      for (var i = 0; i < ids.length; i++) {
        airports.setFeatureStyle(ids[i], {
          color: '#BA454E',
          weight: 2,
          opacity: 0.85,
          fillOpacity: 0.5
        });
      }
    });
  });
</script>

</body>
</html>

Si quieres aprender a crear visores web profesionales como estos, inscríbete ya en nuestro curso online web mapping interactivo con Leaflet.

3 comentarios en «Esri Leaflet: herramientas para usar servicios de ArcGIS con Leaflet»

  1. Hola,
    estoy intentando trabajar con leaflet, pero al invocar servicios de ArcGIS no me aparece con la simbología definida en el servicio (o sea el diseño que se le dio en ArcMap para luego publicarlo), sino que me asigna un icono por defecto.
    ¿Es posible invocar un servicio de esri respetando el diseño definido en el servicio?
    Gracias por tan valiosa información, nos ayudan a mejorar!

      • Hola Jose Luís,
        gracias por responder.
        Yo no quiero asignarle un estilo, lo que quiero es que tome el estilo que ya viene dado por el servicio de ArcGIS.
        Cunado se publica un servicio pasa primero por ArcMap y ahí se le realiza un diseño con la simbología que queremos, transparencia, color, tipo de iconos, se le puede indicar la escala, etc, o sea que el servicio ya viene con el estilo, lo que quiero lograr es que leaflet me reconozca el estilo del servicio que importo.
        Saludos,

Los comentarios están cerrados.