Librería: Leaflet

Descripción: Contiene las 10 funcionalidades más importantes y básicas que debe tener un mapa interactivo.

image.png

Archivo HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="<https://unpkg.com/leaflet@1.9.4/dist/leaflet.css>">
    <link rel="stylesheet" href="style.css">
    <title>10 Funcionalidades</title>
</head>
<body>
    <div id="map"></div>
    <script src="<https://unpkg.com/leaflet@1.9.4/dist/leaflet.js>"></script>
    <script src="script.js"></script>
</body>
</html>

Archivo JavaScript

//Crear el mapa

const map = L.map('map').setView([4.65, -74.1],12);

// Agregar capa base

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

// Agregar marcadores

fetch('data/Cines.geojson')
    .then(res => res.json())
    .then(data => {
        data.features.forEach(feature => {
            const [lon,lat] = feature.geometry.coordinates;
            const nombre = feature.properties.NOMBRE;

            L.marker ([lat,lon])
            .addTo(map)
            .bindPopup(`<strong>${nombre}<strong/>`);

            
        });
    });

// Control de capas

let barriosLayer, viasLayer;

// Hover interactivo

fetch('data/Barrios_bogota.geojson')
.then(res=> res.json())
.then(data => {
    barriosLayer = L.geoJSON(data, {
        style: {
            color: "#3388ff",
            weight: 1,
            fillOpacity: 0.3
        },
        onEachFeature: function (feature, layer){
            const nombreBarrio = feature.properties.BARRIO;

            layer.on({
                mouseover: function (e){
                    e.target.setStyle({
                        weight: 3,
                        color: "#FFD700",
                        fillOpacity: 0.5
                    });
                },
                mouseout: function(e){
                    barriosLayer.resetStyle(e.target);
                }
            });

            layer.bindTooltip(nombreBarrio,{
                permanent: false,
                direction: 'center',
                className: 'tooltip-barrio'
            });
        }
    });
    barriosLayer.addTo(map);
    agregarControlCapas();
});

// Cargar capas geojson con popups

fetch('data/Vias_principales_bogota.geojson')
.then(res=> res.json())
.then(data => {
    viasLayer = L.geoJSON(data, {
        onEachFeature: function (feature,layer){
            const  nombreVia = feature.properties.LABEL;
            layer.bindPopup(`<strong>${nombreVia}<strong/>`)
        }

    });
    viasLayer.addTo(map);
    agregarControlCapas();
});

function agregarControlCapas(){
    if(barriosLayer && viasLayer){
    L.control.layers(null, {
        "Barrios": barriosLayer,
        "Vías": viasLayer
    }).addTo(map);
    }
}

// Detectar clicks en el mapa

map.on('click', function(e) {
    L.popup()
        .setLatLng(e.latlng)
        .setContent("Coordenadas: " + e.latlng.toString())
        .openOn(map);
});

// Dibujar Geometrías

L.circle([4.564105, -74.052143],{
    radius: 1000,
    color: 'red'
}).addTo(map).bindPopup("Radio de 1000 metros");

L.polygon([
    [4.655,-74.11],
    [4.66,-74.1],
    [4.65,-74.09],
    [4.645,-74.1]
], {
    color: 'green'
}
).addTo(map).bindPopup("Zona de interés");

L.polyline([
    [4.64, -74.12],
  [4.645, -74.115],
  [4.65, -74.11],
  [4.655, -74.105]
],{
    color: 'yellow',
    weight: 5
}
).addTo(map).bindPopup("Ruta trazada");

// Control personalizado y zoom animado

const BtnCines = L.Control.extend({
    onAdd: function(){
        const btn = L.DomUtil.create('button');
        btn.innerHTML = 'Cines';
        btn.onclick = () => map.flyTo([4.65,-74.1],14);
        return btn;
    }
});
map.addControl(new BtnCines({position: 'topright'}));

// Escala

L.control.scale({
    position: 'bottomleft',
    metric: true,
    imperial: false,
    maxWidth: 200,
    updateWhenIdle: true
}).addTo(map);

Archivo CSS

#map {
    position: absolute;
    width: 100%;
    height: 100%;
}

.leaflet-control-scale {
    background-color: azure;
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 18px;
    box-shadow: 0 0 5px rgba(0,0,0,0.3);
    color: black;
}