Las teselas vectoriales o vector tiles son datos geográficos, divididos en «teselas» predefinidas de forma cuadrada listas para su transferencia a través de la web. El concepto es similar a los raster tiles, en que la imagen es dividida en partes que se gestionan de forma individualizada, con la consiguiente economía de medios. En un post anterior hemos hablado en profundidad sobre qué son los vector tiles y cómo generarlos.
Esta vez nos centraremos en el uso de vector tiles en Leaflet.
¿Cuándo nos interesa utilizar vector tiles?
Vector tiles es una tecnología emergente que se está imponiendo por su rapidez en la trasmisión de datos web. Es muy útil para trabajar con cantidades muy grandes de información geográfica porque permite manejarla por bloques (teselas). Por tanto no tiene mucho sentido aplicarla para la carga de nuestras capas vectoriales salvo que estas sean muy grandes. Su principal aplicación es para manejar las capas base de los servidores de teselas como mapbox, u OpenStreetMap. Este será el caso que estudiaremos en esta ocasión.
En resumen podemos decir que las principales ventajas del uso de vector tiles son las siguientes:
- La trasferencia de datos se reduce y por lo tanto es más rápida, ya que solo se envían los datos dentro de la ventana gráfica actual y al nivel de zoom seleccionado.
- En comparación con un mapa raster la transferencia de datos también se reduce, porque los datos vectoriales suelen ser más pequeños que los raster.
- Nos permite personalizar el diseño del mapa, ya que el mapa se compone en el propio navegador del usuario.
Para ilustrar lo que estamos diciendo lo mejor será comparar dos mapas a la vez. Utilizaremos en la comparación los mapas base de mapbox. En la vista de la izquierda vemos un mapa de vector tiles y en el de la derecha uno con teselas raster.
Leaflet.VectorGrid
Con este plugin de Leaflet podemos añadir vector tiles a nuestros mapas, en formatos geoJSON, TopoJSON. También se utiliza para añadir las teselas vectoriales de OpenMapTiles, MapBox, MapZen, o ESRI vector tiles. Podemos consultar la documentación, y ver ejemplos en la página del plugin Leaflet.VectorGrid.
Utilizar Leaflet.VectorGrid es muy sencillo. Solo hay que añadir en nuestro código la referencia al plugin.
<script src="https://unpkg.com/leaflet.vectorgrid@1.2.0"></script>
Como hemos indicado anteriormente una de las principales ventajas del empleo de vector tiles es que podemos personalizar los estilos de las capas. En el caso de mapbox disponemos de documentación en su página que nos permite conocer las capas disponibles y sus características. En el siguiente código escribimos el ejemplo de unos estilos aplicados a las diferentes capas que vamos a utilizar en el mapa.
var vectorTileStyling = { water: { fill: true, weight: 1, fillColor: '#06cccc', color: '#06cccc', fillOpacity: 0.2, opacity: 0.4, }, admin: { weight: 1, fillColor: 'pink', color: 'pink', fillOpacity: 0.2, opacity: 0.4 }, waterway: { weight: 1, fillColor: '#2375e0', color: '#2375e0', fillOpacity: 0.2, opacity: 0.4 }, landcover: { fill: true, weight: 1, fillColor: '#53e033', color: '#53e033', fillOpacity: 0.2, opacity: 0.4, }, landuse: { fill: true, weight: 1, fillColor: '#e5b404', color: '#e5b404', fillOpacity: 0.2, opacity: 0.4 }, park: { fill: true, weight: 1, fillColor: '#84ea5b', color: '#84ea5b', fillOpacity: 0.2, opacity: 0.4 }, boundary: { weight: 1, fillColor: '#c545d3', color: '#c545d3', fillOpacity: 0.2, opacity: 0.4 }, aeroway: { weight: 1, fillColor: '#51aeb5', color: '#51aeb5', fillOpacity: 0.2, opacity: 0.4 }, road: { // mapbox & mapzen only weight: 1, fillColor: '#f2b648', color: '#f2b648', fillOpacity: 0.2, opacity: 0.4 }, barrier_line: { // mapbox & mapzen only weight: 1, fillColor: '#f2b648', color: '#f2b648', fillOpacity: 0.2, opacity: 0.4 }, tunnel: { // mapbox only weight: 0.5, fillColor: '#f2b648', color: '#f2b648', fillOpacity: 0.2, opacity: 0.4, // dashArray: [4, 4] }, bridge: { // mapbox only weight: 0.5, fillColor: '#f2b648', color: '#f2b648', fillOpacity: 0.2, opacity: 0.4, // dashArray: [4, 4] }, transportation: { // openmaptiles only weight: 0.5, fillColor: '#f2b648', color: '#f2b648', fillOpacity: 0.2, opacity: 0.4, // dashArray: [4, 4] }, transit: { // mapzen only weight: 0.5, fillColor: '#f2b648', color: '#f2b648', fillOpacity: 0.2, opacity: 0.4, // dashArray: [4, 4] }, building: { fill: true, weight: 1, fillColor: '#2b2b2b', color: '#2b2b2b', fillOpacity: 0.2, opacity: 0.4 }, water_name: { weight: 1, fillColor: '#022c5b', color: '#022c5b', fillOpacity: 0.2, opacity: 0.4 }, transportation_name: { weight: 1, fillColor: '#bc6b38', color: '#bc6b38', fillOpacity: 0.2, opacity: 0.4 }, place: { weight: 1, fillColor: '#f20e93', color: '#f20e93', fillOpacity: 0.2, opacity: 0.4 }, housenumber: { weight: 1, fillColor: '#ef4c8b', color: '#ef4c8b', fillOpacity: 0.2, opacity: 0.4 }, poi: { weight: 1, fillColor: '#3bb50a', color: '#3bb50a', fillOpacity: 0.2, opacity: 0.4 }, /* earth: { // mapzen only fill: true, weight: 1, fillColor: '#c0c0c0', color: '#c0c0c0', fillOpacity: 0.2, opacity: 0.4 }, */ // Do not symbolize some stuff for mapbox country_label: [], marine_label: [], state_label: [], place_label: [], waterway_label: [], poi_label: [], road_label: [], housenum_label: [], // Do not symbolize some stuff for openmaptiles country_name: [], marine_name: [], state_name: [], place_name: [], waterway_name: [], poi_name: [], road_name: [], housenum_name: [], };
Cargando vector tiles
Una vez que tenemos asignados los estilos a las capas que vamos a utilizar en nuestro mapa, accederemos a los diferentes proveedores de teselas vectoriales.
Mapbox
Para utilizar mapbox emplearemos el siguiente código.
var mapboxUrl = "https://{s}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/{z}/{x}/{y}.vector.pbf?access_token={token}"; var mapboxVectorTileOptions = { rendererFactory: L.canvas.tile, attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="https://www.mapbox.com/about/maps/">MapBox</a>', vectorTileLayerStyles: vectorTileStyling, token: 'pk.eyJ1IjoibmFkaXJpbmciLCJhIjoiY2l5MDA5a2xsMDA5eTMxcXV1dWhrNmFlOCJ9.n9cSzQce7iaj8o8eipuuhA' }; var mapboxPbfLayer = L.vectorGrid.protobuf(mapboxUrl, mapboxVectorTileOptions).addTo(map);
OpenMapTiles
OpenMap Tiles convierte los datos de OpenStreetMap en paquetes listos para usar que contienen mosaicos vectoriales para todo el planeta, países individuales y ciudades importantes. Hay una herramienta online que nos permite probar diferentes estilos en cada capa para ver el resultado.
El código que empleamos para visualizar las capas de OpenMapTiles es el siguiente:
var openmaptilesUrl = "https://free-{s}.tilehosting.com/data/v3/{z}/{x}/{y}.pbf.pict?key={key}"; var openmaptilesVectorTileOptions = { rendererFactory: L.canvas.tile, attribution: '<a href="https://openmaptiles.org/">© OpenMapTiles</a>, <a href="http://www.openstreetmap.org/copyright">© OpenStreetMap</a> contributors', vectorTileLayerStyles: vectorTileStyling, subdomains: '0123', key: 'UmmATPUongHdDmIicgs7', maxZoom: 14 }; var openmaptilesPbfLayer = L.vectorGrid.protobuf(openmaptilesUrl, openmaptilesVectorTileOptions).addTo(map);
Mapzen
Mapzen es una plataforma para construir mapas, abierta y accesible enfocada principalmente a datos geológicos, que se basa en OpenStreetMap.
Como mapzen utiliza su propia nomenclatura para las capas tendremos que escribir la equivalencia con relación a las capas que utilizamos cuando asignamos estilos.
vectorTileStyling.buildings = vectorTileStyling.building; vectorTileStyling.boundaries = vectorTileStyling.boundary; vectorTileStyling.places = vectorTileStyling.place; vectorTileStyling.pois = vectorTileStyling.poi; vectorTileStyling.roads = vectorTileStyling.road;
A continuación podemos crear la capa:
var mapzenTilesUrl = "https://tile.mapzen.com/mapzen/vector/v1/all/{z}/{x}/{y}.mvt?api_key={apikey}"; var mapzenVectorTileOptions = { rendererFactory: L.canvas.tile, attribution: '<a href="https://mapzen.com/">© MapZen</a>, <a href="http://www.openstreetmap.org/copyright">© OpenStreetMap</a> contributors', vectorTileLayerStyles: vectorTileStyling, apikey: 'mapzen-cfbEgD9', }; var mapzenTilesPbfLayer = L.vectorGrid.protobuf(mapzenTilesUrl, mapzenVectorTileOptions).addTo(map);
Hay otra formas de usar teselas vectoriales en Leaflet: mediante el plugin mapbox-gl-leaflet.
Si quieres aprender a crear visores web profesionales como estos, inscríbete ya en nuestro curso online visores webmapping con Leaflet.
Tutor del curso online de Análisis GeoEspacial con Python y de los cursos online de webmapping. Echa un vistazo a todos nuestros cursos de SIG online.
Hola Willman
Es posible generar teselas vectoriales mediante PostGIS 2.4 o con Geoserver 2.11.0. Te aconsejo que leas este artículo en el blog de Mappinggis. https://mappinggis.com/2017/09/que-son-los-vector-tiles-y-como-generarlos-con-geoserver/
Saludos
Hola, en el caso de OpenMapTiles, te limita al máximo de zoom a 14, lo cual no permite tener una mejor vista del área que se desea mostrar, hice la prueba usando TileServer en mi pc como servidor local, pero, no ayuda mucho en ese sentido, me podrían ayudar de como poder obtener generar una tesela vectorial de una zona pero sin la limitación del zoom, muchas gracias.