Leaflet en acción: visualización de datos geoespaciales desde PostGIS, GeoServer y QGIS

Si alguna vez te has preguntado cómo crear mapas web que se vean bonitos, interactivos y que además estén conectados a datos espaciales reales, la respuesta se llama Leaflet. Pero Leaflet no trabaja solo: cuando lo conectamos con PostGIS, GeoServer y QGIS, el resultado es una sinfonía de datos actualizados, bien organizados y fácilmente visualizables. En este artículo vamos a ver cómo estas herramientas se integran paso a paso.


La gestión de datos geoespaciales implica la recopilación, almacenamiento, análisis y visualización de datos que tienen una referencia geográfica. Estos datos pueden representar cualquier cosa, desde la ubicación de árboles en un parque hasta la distribución de enfermedades en una región.

Aquí es donde entra PostGIS, GeoServer y QGIS para ayudarnos a publicar estos datos geoespaciales a nuestros mapas interactivos:

PostGIS: potenciando PostgreSQL con datos espaciales

PostGIS es una extensión de la base de datos PostgreSQL que permite almacenar y consultar datos espaciales. Con PostGIS, puedes realizar operaciones como calcular distancias entre puntos, encontrar intersecciones entre polígonos y mucho más.

Ventajas de usar PostGIS:

  • Integración con PostgreSQL: Aprovecha todas las características de una base de datos relacional robusta.
  • Soporte para estándares OGC: Asegura la interoperabilidad con otras herramientas y sistemas.
  • Amplia comunidad: Abundante documentación y soporte de la comunidad.

Paso 1. Crear una Base de Datos

  • Click derecho sobre “Databases” -> “Create” -> “Database”

Menú contextual de pgAdmin sobre Databases con la opción Create, Database

  • En Database dale un nombre y guarda:

Ventana Create Database de pgAdmin con el nombre Cali y el usuario postgres como dueño

Paso 2. Activar PostGIS

  • Click derecho sobre la nueva Base de Datos “cali” -> “Create” -> “Extension”

Menú contextual de la base de datos cali en pgAdmin con la opción Create, Extension

  • En Name selecciona “postgis” y guarda:

Ventana Create Extension de pgAdmin con postgis seleccionado en el campo Name


QGIS: Visualizando y Editando Datos Espaciales

Con QGIS puedes cargar capas, visualizar mapas y preparar tus datos para ser usados en otras herramientas.

Paso 1: Cargar un shapefile en QGIS

  • Abre QGIS
  • Ve a “Layer” -> “Add Layer” -> “Add Vector Layer”

Menú Layer de QGIS con la ruta Add Layer, Add Vector Layer para cargar el shapefile

  • En “Source” busca y selecciona tu archivo .shp
  • Luego “Add”

Paso 2: Crear una conexión a PostGIS

  • Ve a “Browser” -> “PostgreSQL” -> “New Connection”

Panel Browser de QGIS con la opción New Connection sobre PostgreSQL

  • Crea una nueva conexión con:
    • Name: Nombre de la conexión
    • Host: localhost o IP del servidor
    • Port: 5432
    • Database: tal cual como la tengas creada en PostgreSQL
    • User name: postgres
    • Password: la que hayas definido en la instalación

Formulario de nueva conexión PostGIS en QGIS con host localhost, puerto 5432 y base de datos cali

Paso 3: Migrar el shapefile a PostGIS

  • Ve a “Database” desde el menú -> “DB Manager”

Menú Database de QGIS con la opción DB Manager

  • Seleccionar la conexión de “PostGIS” -> “nombre de la conexión”

DB Manager de QGIS con la conexión con_cali seleccionada dentro de PostGIS

  • Ingresa las Credenciales de conexión a tu base de datos:

Ventana de QGIS que pide usuario y contraseña para conectarse a la base de datos cali

  • Ahora ve a “Import Layer/File” -> selecciona la capa .shp -> el esquema Public -> escribe el nombre de la tabla que va a quedar en PostgreSQL y da check en las siguientes opciones:

Ventana Import vector layer con la tabla Barrios_Cali en el esquema public, llave primaria e índice espacial

  • Espera a que finalice la importación:

Mensaje de QGIS que confirma que la importación a la base de datos terminó bien

Ahora tus datos ya están en PostGIS y listos para ser usados por GeoServer.


GeoServer: Publicando tus datos para la web

GeoServer es el puente que permite exponer tus datos desde PostGIS hacia aplicaciones web como Leaflet.

Publicar una capa de PostGIS en GeoServer

  • Ingresa a http://localhost:8080/geoserver

  • Crea un “Workspace” (por ejemplo: cali)

Formulario de GeoServer para crear el espacio de trabajo cali

  • Crea un “Almacen de datos” tipo “PostGIS” con tu conexión a la base de datos

Almacén de datos PostGIS en GeoServer con los parámetros de conexión a la base de datos cali

  • Desde “Capas” pulsa “Agregar nueva capa” -> selecciona el almacen de datos -> “Publicación” sobre la capa que desees

Pantalla Nueva capa de GeoServer con la tabla Barrios_Cali lista para publicar desde postgis_cali

  • Configura nombre, el sistema de referencia (SRS), nombre, estilo, etc.

Edición de la capa cali:Barrios_Cali en GeoServer con el nombre y el título marcados

Sistema de referencia EPSG:4326 y encuadres calculados de la capa en GeoServer

  • Guarda y prueba que se pueda visualizar como WMS/WFS desde “Publicacion de capas”

Previsualización de capas de GeoServer con Barrios_Cali y el selector de todos los formatos

Lista de formatos WFS de GeoServer con GeoJSON seleccionado

Con la url ya puedes obtener los datos requeridos para mostrarlo desde Leaflet:

Navegador con la URL WFS de GeoServer y la respuesta GeoJSON de los barrios de Cali

http://localhost:8080/geoserver/cali/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=cali%3ABarrios\_Cali&maxFeatures=50&outputFormat=application%2Fjson

baseUrl=http://localhost:8080/geoserver/cali/ows

service=WFS

version=1.0.0

request=GetFeature

typeName=cali:Barrios_Cali

outputFormat=application/json

Con GeoServer, puedes servir tus datos a aplicaciones web y otros clientes que soporten estos estándares.


Leaflet: Visualizando datos geoespaciales en la web

Ahora viene la parte divertida: hacer que nuestros datos se vean en la web con Leaflet.

Conectando Leaflet con datos desde GeoServer (WFS)

Usando la url generado del WFS desde GeoServer construye la baseUrl para mostrarla en el mapa.

  • Crea un archivo llamado mapa.js
const map = L.map('map').setView([3.42, -76.52], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,
  attribution: '© OpenStreetMap'
}).addTo(map);

//Crear la baseUrl a partir de la publicación en GeoServer 
var baseUrl = 'http://localhost:8080/geoserver/cali/ows';
var defaultParameters = {
  service: 'WFS',
  version: '1.0.0',
  request: 'GetFeature',
  typeName: 'cali:Barrios_Cali',
  outputFormat: 'application/json'
};

var parameters = L.Util.extend(defaultParameters);
var URL = baseUrl + L.Util.getParamString(parameters);

//Definir como mostrar la capa desde GeoServer
$.ajax({
  url: URL,
  success: function (data) {
    var geojson = new L.geoJson(data, {
      style: {"color":"#063970","weight":1},
      onEachFeature: function(feature, layer){
        layer.bindPopup("El barrio seleccionado es " + feature.properties.nombre);
      }}
    ).addTo(map);
  }
});
  • Crea un archivo llamado mapa.html
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="utf-8" />
  <title>Datos desde PostGIS</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />  
  <link rel="stylesheet" href="mapa.css" />
</head>

<body>
  <div id="map"></div>
  <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
  <script src="https://code.jquery.com/jquery-3.2.1.js" ></script>
  <script src="mapa.js"></script>
</body>

</html>
  • Crea un archivo llamado mapa.css
#map {
    position: absolute;
    width: 100%;
    height: 100%;
}
  • Ahora abre mapa.html. Verifica que se muestre tu capa de PostGIS. Si no se muestra la capa, haz lo siguiente:

  • Click derecho sobre el mapa base -> “Inspeccionar” (Inspect)

Mapa base de Cali en el navegador con el menú contextual abierto en la opción Inspeccionar

  • En el siguiente listado de la derecha selecciona “Console”:

Herramientas de desarrollo del navegador con la pestaña Console marcada

  • Si ves este error de CORS:

Consola del navegador con el error de CORS al pedir la capa WFS a GeoServer

  • Debes instalar una extension de Chrome llamada CORS y habilitarla. Esto hace que cargue el navegador sin problemas. Un error CORS se produce cuando un navegador no puede acceder a un recurso de otro dominio porque el servidor del recurso no ha configurado correctamente los encabezados CORS.

Extensión CORS de Chrome abierta con el interruptor ON y OFF marcado

  • Recarga tu mapa y ya podras verlo con la capa traida desde PostGis:

Mapa de Leaflet con los barrios de Cali cargados desde PostGIS a través de GeoServer


Quieres aprender algo extra?

Crea un mapa de Calor en Leaflet desde un archivo GeoJSON

Un mapa de calor es ideal para mostrar dónde se concentran ciertos eventos (por ejemplo: puntos de crímenes, densidad de árboles, población, entre otros).

Estructura general del código:

  1. Cargar archivo GeoJSON desde un input
  2. Identificar centroides para líneas y polígonos
  3. Detectar campos numéricos para intensidad
  4. Dibujar el mapa de calor con L.heatLayer
// Inicializar el mapa
const map = L.map('map').setView([6.24576, -75.59087], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap'
}).addTo(map);

let geojsonDataGlobal = null;
let heatLayer = null;
const campoSelect = document.getElementById('campo-intensidad');

//Crear centroides para polígonos y líneas
function getPolygonCentroid(coords) {
  try {
    let area = 0.0, x = 0.0, y = 0.0;
    const points = coords[0];
    for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
      const [x0, y0] = points[j];
      const [x1, y1] = points[i];
      const a = x0 * y1 - x1 * y0;
      area += a;
      x += (x0 + x1) * a;
      y += (y0 + y1) * a;
    }
    area *= 0.5;
    const factor = 1 / (6 * area);
    return [y * factor, x * factor];
  } catch (e) {
    console.error("Error centroide polígono:", e);
    return null;
  }
}

function getLineCentroid(coords) {
  let lat = 0, lng = 0;
  coords.forEach(([lon, latVal]) => {
    lng += lon;
    lat += latVal;
  });
  return [lat / coords.length, lng / coords.length];
}

//Obtener los campos numericos de la capa cargada Geojson
function obtenerCamposNumericos(properties) {
  const campos = [];
  for (const key in properties) {
    if (typeof properties[key] === 'number') {
      campos.push(key);
    }
  }
  return campos;
}

// Construir el mapa de calor con L.heatLayer
function construirHeatmap(geojson, campo) {
  const heatData = [];
  geojson.features.forEach(feature => {
    let coords;
    const geom = feature.geometry;
    if (!geom || !feature.properties) return;

    if (geom.type === 'Point') {
      coords = [geom.coordinates[1], geom.coordinates[0]];
    } else if (geom.type === 'Polygon') {
      coords = getPolygonCentroid(geom.coordinates);
    } else if (geom.type === 'LineString') {
      coords = getLineCentroid(geom.coordinates);
    } else if (geom.type === 'MultiPolygon') {
      coords = getPolygonCentroid(geom.coordinates[0]);
    } else {
      console.warn("Geometría no soportada:", geom.type);
      return;
    }

    const valor = parseFloat(feature.properties[campo]);
    if (!isNaN(valor) && coords) {
      heatData.push([coords[0], coords[1], valor]);
    }
  });

  if (heatLayer) {
    map.removeLayer(heatLayer);
  }

  heatLayer = L.heatLayer(heatData, {
    radius: 30,
    blur: 20,
    maxZoom: 17
  }).addTo(map);
}

//Función para cargar el archivo Geojson
document.getElementById('geojson-upload').addEventListener('change', function (e) {
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = function (event) {
    const geojson = JSON.parse(event.target.result);
    geojsonDataGlobal = geojson;

    let camposNumericos = [];
    for (let f of geojson.features) {
      if (f.properties) {
        camposNumericos = obtenerCamposNumericos(f.properties);
        if (camposNumericos.length > 0) break;
      }
    }

    campoSelect.innerHTML = '';
    camposNumericos.forEach(campo => {
      const opt = document.createElement('option');
      opt.value = campo;
      opt.textContent = campo;
      campoSelect.appendChild(opt);
    });
    campoSelect.disabled = false;

    construirHeatmap(geojsonDataGlobal, camposNumericos[0]);
  };
  reader.readAsText(file);
});

campoSelect.addEventListener('change', function () {
  const campo = campoSelect.value;
  if (geojsonDataGlobal && campo) {
    construirHeatmap(geojsonDataGlobal, campo);
  }
});

Mapa de calor en Leaflet de bancos de Medellín cargados desde un GeoJSON con el campo de intensidad


Puedes ver todo el paso a paso aquí:

Video de YouTube

Para verlo aquí, enciende la capa de contenido externo.

Abrir en YouTube

La gestión de datos geoespaciales es fundamental en muchas aplicaciones modernas, desde la planificación urbana hasta el monitoreo ambiental. Herramientas como PostGIS, QGIS, GeoServer y Leaflet trabajan juntas para facilitar este proceso, permitiendo a profesionales y desarrolladores crear soluciones poderosas y accesibles.

Si quieres seguir aprendiendo sobre mapas web y SIG, visita mi canal de YouTube: https://www.youtube.com/channel/UCbiz5hEvp5O2OSCB_3VVGww y únete a la comunidad en Discord: https://discord.gg/6s86Gc8Vfk

WhatsApp