Librerías JavaScript - creación de mapas con LeafletJS

Damián Aguilar twitter - 20/10/2020

javascript livewire alpinejs

Según wikipedia1 un servicio WMS produce mapas de datos referenciados espacialmente, de forma dinámica a partir de información geográfica. Es decir, estamos hablando de servicios como GoogleMaps, OpenStreetMap o similares. Se trata entonces de capas de información que se muestran superpuestas y en forma de mapa.

Podemos integrar estos servicios en nuestro proyecto web, mediante la librería LeafletJS

Lo primero que tenemos que hacer es instalarla en nuestro proyecto. En el <head> de nuestra web, añadimos el código css y JavaScript:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
   integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
   crossorigin=""/>
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
  integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
  crossorigin=""></script>

Advierten de que pongas primero el css y después el JavaScript, tal y como se muestra en el ejemplo.

Lo primero que tenemos que hacer es definir las variables por defecto:

var lat = '37.7634109';
var lng = '-0.7700499';
var maxZoom = '18';
var zoom = '12';
var map;

Tenemos que definir la latitud y la longitud donde queremos que se centre el mapa que vamos a generar. Continuamos con el zoom máximo que vamos a permitir (y que permite el sistema WMS) y con el zoom por defecto que se mostrará al cargar el mapa. Por último, hay que definir la variable donde se creará el mapa. Ahora ya podemos crear el mapa:

this.map = L.map('mapContainer').setView([lat, lng], this.zoom);

L.tileLayer.wms( '//www.ign.es/wms-inspire/pnoa-ma', {
    attribution: '<a href="http://www.ign.es" target="_blank">© Instituto Geográfico Nacional</a>',
    layers: 'OI.OrthoimageCoverage',
    format: 'image/jpeg',
    transparent: false,
    version: '1.3.0',
    crs: L.CRS.EPSG4326,
    maxZoom: this.maxZoom
}).addTo( this.map );

En principio ya estaría terminado, ahora tenemos que crear un div con el identificador mapContainer (por ejemplo) donde se mostrará el mapa:

<div id="mapContainer" style="width: 400px; height: 400px;"></div>

Obviamente, pudes poner el nombre que quieras al contenedor:

this.map = L.map('elNombreQueQuieras').setView([lat, lng], this.zoom);

Es importante definir el ancho y el alto del contenedor, o no se mostrará nada, ya que si no indicamos nada nos creará un contenedor de ancho 0 y alto 0.

Ahora podemos refinarlo on poco:

var lat = '37.7634109';
var lng = '-0.7700499';
var maxZoom = '18';
var zoom = '12';
var map;

this.createMap('mapContainer');

function createMap(mapID) {
    this.map = L.map(mapID).setView([lat, lng], this.zoom);

    L.tileLayer.wms( '//www.ign.es/wms-inspire/pnoa-ma', {
        attribution: '<a href="http://www.ign.es" target="_blank">© Instituto Geográfico Nacional</a>',
        layers: 'OI.OrthoimageCoverage',
        format: 'image/jpeg',
        transparent: false,
        version: '1.3.0',
        crs: L.CRS.EPSG4326,
        maxZoom: this.maxZoom
    }).addTo( this.map );
}

Vale, expliquemos un poco el código. Lo primero es buscar un servicio WMS gratuito, en este caso es del Instituto Geográfico Nacional2 de España, pero existen cientos... ya es cuestión de que busques el que más te interesa. En mi caso, suelo utilizar este WMS para mostrar mapas de España.

Los campos que deben indicarse para conectar con el servicio WMS son:

¿Y si queremos añadir un marcador al mapa indicando el punto exacto de las coordenadas?

Pues creamos un marcador y lo añadimos al mapa:

var marker = L.marker( new L.LatLng( this.lat, this.lng ) ).addTo( this.map );

En este caso estoy indicando que use las mismas coordenadas de latitud y longitud, pero se puden poner otras... o incluso varias. Para esto tendremos que añadir un marcador por cada punto.

Un último consejo, sobre todo si vamos a incluir el mapa con librerías reactivas tipo VueJS o AplineJS. En estos casos es preferible añadir una recarga del mapa una vez generada la página... por si acaso:

function reloadMap() {
    setTimeout(function(){ this.map.invalidateSize() }, 200);
}

Todo junto quedaría así:

var lat = '37.7634109';
var lng = '-0.7700499';
var maxZoom = '18';
var zoom = '12';
var map, marker;

this.createMap('mapContainer');

this.marker = L.marker( new L.LatLng( this.lat, this.lng ) ).addTo( this.map );

function createMap(mapID) {
    this.map = L.map(mapID).setView([lat, lng], this.zoom);

    L.tileLayer.wms( '//www.ign.es/wms-inspire/pnoa-ma', {
        attribution: '<a href="http://www.ign.es" target="_blank">© Instituto Geográfico Nacional</a>',
        layers: 'OI.OrthoimageCoverage',
        format: 'image/jpeg',
        transparent: false,
        version: '1.3.0',
        crs: L.CRS.EPSG4326,
        maxZoom: this.maxZoom
    }).addTo( this.map );

    this.reloadMap();
}

function reloadMap() {
    setTimeout(function(){ this.map.invalidateSize() }, 200);
}

Esto último método reloadMap(), es básico si el proyecto utiliza Livewire, AlpineJS, Laravel Nova, VueJS...

En la web oficial de Leaflet vas a encontrar muchos ejemplos:

Referencias

  1. https://es.wikipedia.org/wiki/Web_Map_Service
  2. http://www.ign.es/web/ign/portal
  3. https://ingecivilcusco.blogspot.com/2009/09/sistema-geodesico-mundial-1984-wgs84.html