Leaflet: un’alternativa a Google Maps (Gmaps) per inserire mappe interattive in un sito

Aggiornato il

Tempo fa ho mostrato attraverso questo tutorial come creare una mappa interattiva con Google Maps. Questa volta invece vorrei parlare di un suo diretto “concorrente”: Leaflet.

Il progetto Leaflet

Leaftlet è una libreria open source JavaScript estremamente leggera (solo 33KB di peso!), che come Gmaps permette di inserire mappe dinamiche all’interno di un sito. Ha largo supporto sui maggiori browsers e nasce con l’intento di essere ottimale sui dispositivi portatili. Pur essendo uno strumento per sviluppatori (puoi anche contribuire al progetto su GitHub), la sua semplicità è tale da renderlo veramente alla portata di tutti.

Nel sito web per una birreria artigianale che ho realizzato di recente (ah, fateci un salto se ci passate: la birra lì è davvero divina!) ho creato in pochi passi una funzionalissima mappa interattiva. Spiegherò come ho fatto attraverso questo tutorial, tenendo conto che il risultato che voglio ottenere è il seguente:

Mappa interattiva con Leaflet

Fig. 1: mappa interattiva con Leaflet

Settaggio iniziale

La prima cosa che devi fare è importare il file CSS di Leaflet all’interno della <head> della tua pagina:



<head>

    <!-- Leaflet CSS -->
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css" />

</head>


Subito prima della chiusura del tag <body> invece, inserisci il richiamo ai file JavaScript (cioè alla libreria vera e propria):



<!-- ... -->

<!-- Leaflet JS -->
<script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

</body>


E’ sempre buona cosa inserire il codice JavaScript appena prima della chiusura del tag <body> (quando possibile, e non solo nel caso di Leaflet!): se durante il caricamento delle sue funzioni si verificassero infatti dei problemi, tutto il contenuto che si trova dopo rischierebbe di “bloccarsi”. Mettendo il codice in fondo alla pagina quindi, limiti i “danni”.

Bene, crea ora un elemento <div> all’interno della pagina (a seconda di dove vuoi far apparire la mappa) ed assegnagli un id="map":



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


Sfruttando il CSS, imposta almeno il valore dell’altezza:



#map {

    height: 180px;
}


In quattro semplici passaggi hai così creato il “contenitore” della mappa: non ti resta ora che riempirlo di “vita”!

Creazione della mappa interattiva

Sempre prima della chiusura del tag <body>, e per la precisione dopo il tag <script> creato nei punti precedenti, inserisci nel codice:



<!-- Leaflet JS -->
<script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

<script type="text/javascript">

    var map = L.map('map').setView([44.801327, 10.327835], 13);

</script>


Hai impostato così una mappa con i seguenti parametri:

  • Le coordinate della città Parma: 44.801327, 10.327835
  • Il livello iniziale di Zoom della mappa: 13

Ottenere le coordinate è molto semplice, e puoi farlo ad esempio con il servizio di OpenStreetMap: visita la homepage di OpenStreetMap, dove troverai una mappa molto simile a quella di Google. In alto a sinisra, nella sezione “cerca”, inserisci la città o il luogo di interesse del quale ti interessano le coordinate.

Una volta filtrati i risultati, clicca ancora una volta sul pulsante “dove sono” (sempre all’interno del campo della ricerca). Copia le coordinate di latitudine e longitudine che ti apparirano dopo il click, e il gioco è fatto! (Fig. 2)

Coordinate con OpenStreetMap

Fig. 2: reperire le coordinate con OpenStreetMap

Per essere funzionale però, la mappa ha ancora bisogno di veste grafica (per adesso non è altro che un rettangolo “cieco”! ). (Fig. 3)

Mappa Leaflet senza layer

Fig. 3: la mappa interattiva (ancora priva di veste grafica)

Stilizzare la mappa

Leaflet è un servizio open source e permette quindi di caricare varie tipologie di mappe da qualsiasi servizio di terze parti che le supporti. Sul sito di Leaflet ti consigliano di utilizzare CloudMade, che possiede anche un editor interattivo (inoltre, Leaflet è a tutti gli effetti un prodotto del gruppo CloudMade!). A mio avviso però, CloudMade è un tantino complicato da impostare (e per farlo sei obbligato a registrarti).

Preferendo rimanere sul semplice, ho deciso in questo tutorial di affidarmi sempre a OpenStreetMap! Per dare un “vestito” alla tua mappa, bisogna impostare la proprietà tileLayer. Al codice precedentemente creato aggiungi quindi:



<!-- Leaflet JS -->
<script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

<script type="text/javascript">

    var map = L.map('map').setView([44.801327, 10.327835], 13);

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
    maxZoom: 18
    }).addTo(map);

</script>


Ho qui inserito:

  • L’URL della mappa (un file di immagine): http://{s}.tile.osm.org/{z}/{x}/{y}.png
  • L’attribuzione dei crediti al servizio OpenStreetMap: © <a href="http://osm.org/copyright">OpenStreetMap</a> contributors
  • Il massimo livello di Zoom della mappa: 18

A questo punto, dovresti vedere anche tu una mappa dinamica e funzionante che mostra il centro di Parma (my “boring” city!):

Mappa Leaflet con layer

Fig. 4: il centro di Parma sulla mappa

Non resta che aggiungere il segnaposto e… qualcos’altro!

Aggiunta del segnaposto (marker)

Aggiungere un segnaposto (cioè la poprietà marker) è semplicissimo: dal momento che lo voglio puntato esattamente al centro della mappa, le coordinate rispetto a prima non cambiano:



<!-- Leaflet JS -->
<script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

<script type="text/javascript">

    var map = L.map('map').setView([44.801327, 10.327835], 13);

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
    maxZoom: 18
    }).addTo(map);

    var marker = L.marker([44.801327, 10.327835]).addTo(map);

</script>


Et voilà, il marker eccolo qua.

Mappa Leaflet con marker (segnaposto)

Fig. 5: il segnaposto è al centro della mappa

Inserire figure geometriche

Leaflet permette anche di utilizzare alcune forme geometriche in pochissimi passaggi. Per inserire ad esempio un cerchio in sostituzione del segnaposto, modifica in questo modo il codice che hai scritto prima:



<!-- Leaflet JS -->
<script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

<script type="text/javascript">

    var map = L.map('map').setView([44.801327, 10.327835], 13);

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
    maxZoom: 18
    }).addTo(map);

    var circle = L.circle([44.801327, 10.327835], 500, {
    color: '#ff0000',
    fillColor: '#00ff00',
    fillOpacity: 0.5
    }).addTo(map);

</script>


I parametri che ho inserito riguardano:

  • Le coordinate del centro del cerchio: 44.801327, 10.327835
  • La lunghezza del raggio (misurato in metri sulla mappa): 500
  • Il colore del contorno: color: '#ff0000'
  • Il colore di riempimento: fillColor: '#00ff00'
  • La trasparenza del colore di riempimento: fillOpacity: 0.5

Ho anche eliminato il segnaposto, ma non era affatto necessario: le due figure potevano convivere tranquillamente sulla stessa mappa! Ecco comunque come appare il mio cerchio:

Mappa Leaflet con cerchio

Fig. 6: la mappa con il cerchio

Al posto del cerchio preferisci un poligono? Ecco come fare:



<!-- Leaflet JS -->
<script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

<script type="text/javascript">

    var map = L.map('map').setView([44.801327, 10.327835], 13);

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
    maxZoom: 18
    }).addTo(map);

    var polygon = L.polygon([
    [44.811327, 10.325835],
    [44.801327, 10.315835],
    [44.791327, 10.335835],
    [44.805327, 10.337335]
    ],{
    color: '#ff0000',
    fillColor: '#0000ff',
    fillOpacity: 0.5
    }).addTo(map);

</script>


Dal momento che il poligono che ho scelto è formato da quattro lati (ne avresti potuto comunque aggiungere altri), le coordinate che vedi tra le parentesi quadre rappresentano i relativi “punti di ancoraggio”. Gli altri parametri sono gli stessi usati per il cerchio.

Ecco come appare la mappa con il poligono:

Mappa Leaflet con poligono

Fig. 7: la mappa con il poligono

Rimane solo un’ultima cosa da fare: aggiungere la nuvoletta con il testo!

Aggiunta della finestra popup

Ritorno alla situazione di partenza, cioè quella con la sola presenza del segnaposto. Inserire la nuvoletta con il testo è immediato! Ecco il codice:



<!-- Leaflet JS -->
<script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

<script type="text/javascript">

    var map = L.map('map').setView([44.801327, 10.327835], 13);

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
    maxZoom: 18
    }).addTo(map);

    var marker = L.marker([44.801327, 10.327835]).addTo(map);

    marker.bindPopup("<b>Ciao!</b><br>Mi trovo a Parma").openPopup();

</script>


Come vedi, puoi stilizzare il testo che appare dentro la nuvoletta sfruttando il linguaggio HTML. L’istruzione .openPopup() che vedi alla fine della stringa invece, fa sì che la finestrella rimanga aperta di default: se la elimini, per vedere la nuvoletta dovrai cliccare con il mouse sul segnaposto.

Ecco dunque il risultato finale:

Mappa Leaflet completa

Fig. 8: la mappa interattiva al completo

Riporto qui tutto il codice della pagina come riferimento:



<!DOCTYPE html>

<html>

<head>

    <!-- Leaflet CSS -->
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css" />

    <style>

        #map {

            height: 400px;
        }

    </style>

</head>

<body>

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

    <!-- Leaflet JS -->
    <script src="https://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>
    <script type="text/javascript">

    var map = L.map('map').setView([44.801327, 10.327835], 13);

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
        attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
        maxZoom: 18
    }).addTo(map);

    var marker = L.marker([44.801327, 10.327835]).addTo(map);

    marker.bindPopup("<b>Ciao!</b><br>Mi trovo a Parma").openPopup();

    </script>

</body>

</html>



Conclusioni finali: Gmaps e Leaflet a confronto

Rispetto a Google Maps, Leaflet è un servizio molto recente che ha ottenuto in breve tempo un sacco di popolarità. Devo dire che è davvero pratico e veloce, cosa che lo rende molto allettante per i dispositivi portatili. Proprio perché ancora relativamente “nuovo” però, le sue API non sono ancora così potenti e ricche di features come quelle di “Big G”.

Il suo punto forte rimane comunque la flessibilità: è largamente customizzabile grazie al potente object model su cui è stato realizzato, mentre la sola possibilità di incorporare infinite tipologie di mappe da altri servizi esterni, se ci pensi, non è cosa da poco!

E tu, cosa ne pensi di Leaflet? Potrebbe farti dimenticare totalmente le mappe di Google?

Approfondimenti

di Mattia Frigeri

COMMENTI

  • Buonasera Mattia,

    Intanto complimenti per lo script, un vero colpo da maestro. Ho una domanda da porle a riguardo, se volessi inserire lo script in un sito con CMS WordPress come dovrei procedere per quanto riguarda l’inserimento del codice?

    Saluti e grazie

    Marco Rossmann

    • Salve Marco, per quanto riguarda WordPress, la faccenda è un po’ più complessa. Ci sono varie opzioni, ma quella che mi sento di consigliarle (in quanto corretta) è anche la più complessa, e dipende dal suo livello di conoscenza di manipolazione del CMS.
      Consiste nello sfruttare il file functions.php del suo tema, e caricare lo script direttamente da lì. Meglio ancora con un condizionale, per essere sicuro di non appesantire le pagine in cui non serve. Trova qui un ottimo tutorial (in lingua inglese). Come la vede?

      • Salve Mattia,

        intanto grazie per la sua rapida e precisa risposta, da quello che ho capito dal suo messaggio e dalla guida in inglese bisogna inserire nella pagina functions.php la parte di codice contenuta nei tag mentre per visualizzarla con marker, aree e pop-up si lavora nelle pagine WordPress inserendo il codice come fatto nei tag del suo esempio.

        Nei prossimi giorni farà un paio di prove e la aggiorno.

        Saluti, Marco

        • Salve Marco, risponderei con un “ni”.
          Se lei non ha esperienza con questo tipo di operazioni, rischierebbe di “guastare” il tema, o non ottenere nulla. La cosa di sicuro più semplice in questo caso (per i puristi, sto per dire una “bestemmia”) è modificare direttamente i 2 file principali del template: header.php e footer.php, inserendo gli script tra il loro codice, nella modalità suggerita dal mio esempio (si dice fare dell’hardcode, in gergo tecnico). Mi riesce tuttavia difficile spiegarle per bene il corretto procedimento qui nei commenti… mi faccia sapere.

  • Ciao Mattia, sul sito della birreria la mappa non si vede su tutti i browser: IE 10, Opera, Firefox, Safari e Chrome.

    Cos’è successo? Mi interessa perchè vorrei usarlo anche io sul mio sito.

    Grazie

    • Ciao Francesco, grazie della segnalazione.
      Indagherò: con tutta probabilità è stato modificato il file sorgente del provider, o qualche metodo. Scriverò qui la soluzione una volta scoperta!

    • Ciao Francesco, il problema è stato risolto (scusa il ritardo nella risposta). Come avevo intuito, il provider con cui era stata creata la mappa del sito della birreria è stato “spento”. In ogni caso, il tutorial era corretto poiché si affida a un diverso provider. Grazie a te ho comunque sistemato l’errore sul sito, quindi ti devo una… birra. ;)