Classi 4D e 4E: Crea la tua prima mappa con LeafletJS

Crea la tua prima mappa con LeafletJS



LeafletJS (o semplicemente Leaflet) è ormai da anni uno degli strumenti più diffusi e se vogliamo più semplici, per pubblicare delle mappe all’interno di una pagina web.

Come molti di voi sapranno già, si tratta di una libreria JavaScript open source che nasce per realizzare mappe interattive per applicazioni “mobile”, ma che poi si è diffusa ampiamente anche per il web mapping in generale, grazie alle sue principali doti: è molto leggera (il suo codice .js totale pesa solo 33KB), è molto versatile e facile da usare (ha delle API ben documentate) ed esistono molti plugins che ne estendono le funzionalità.

Tra l’altro il suo sito ufficiale (leafletjs.com) è ricchissimo di documentazione, tutorial ed esempi pratici già realizzati.

Ciò tuttavia molte volte chi si approccia ad usare Leaflet per la prima volta, non sa esattamente come cominciare e magari si confonde tra le tante informazioni che sono disponibili.

Allora in questo articolo vorrei fornire una guida minima che indichi passo-passo a chi vuole cimentarsi nel realizzare una pagina web che contenga una mappa con alcune funzionalità elementari, che cosa deve fare.
Cosa ci serve per usare LeafletJS

Una premessa è d’obbligo. Pur essendo Leaflet una libreria molto semplice, per poterla usare bisogna comunque scrivere direttamente delle pagine HTML, usando codice JavaScript e fogli di stile (CSS); quindi, anche se non è necessario essere un esperto web designer, è bene comunque masticarne un po’ di questi tre linguaggi: HTML, CSS e JavaScript.

La pagina web che deve contenere la mappa quindi va editata a mano e per farlo si può usare un qualunque IDE adatto per realizzare pagine web e/o programmare in JavaScript (quello che voi preferite !) o più semplicemente un normale text editor come “notepad”.

Tuttavia è meglio usare un editor specifico per la scrittura in HTML e JavaScript, cioè con quelle funzionalità di completamento ed evidenza del codice che sono di aiuto per una programmazione più agevole. Tanto per fare qualche esempio, editor come: PSPad, Sublime Text e Notepad++.

Bene, fatte queste premesse, per cominciare a scrivere la nostra pagina web che conterrà la mappa, dobbiamo ovviamente avere a disposizione : 
la libreria Javascript di Leaflet 
il foglio di stile CSS di Leaflet 

e per fare questo abbiamo due possibilità:

a) scaricarli sul nostro computer;

b) riferire questi file (libreria e CSS) in remoto sul server CDN di Leaflet (cdn.leafletjs.com);

sia per scaricarli (c’è un file .zip che li contiene) sia per conoscere i link CDN dell’ultima versione stabile di Leaflet (al momento è la 0.7.7), basta andare sulla pagina: leafletjs.com/download.html .


In base a cosa scegliamo, indicheremo nell’ <head>…</head> della nostra pagina web il riferimento ad essi, come mostrato di seguito (per i due casi) :

<html>
<head>
<title>La mia prima mappa con Leaflet</title>
<!-- nel caso a -->
<link rel="stylesheet" href="./leaflet/leaflet.css"/>
<script src="./leaflet/leaflet.js"</script>;
<!-- nel caso b -->
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
</head>
<body>
....
....
</body>
</html>

In questo modo si hanno le indicazioni per poter richiamare correttamente gli stili e le funzioni JavaScript resi disponibili da Leaflet. Per l’esempio che faremo in questo articolo, ci riferiremo alla scelta b).
Il contenitore della mappa

Adesso nel <body> della pagina inseriamo dove vogliamo, l’elemento <div> fondamentale perchè è quello che dovrà contenere la nostra mappa e gli assegniamo un id=mymap; inoltre, usando il CSS, nella sezione <head> definiamo almeno le sue dimensioni: larghezza e altezza o almeno una delle due.

<html>
<head>
<title>La mia prima mappa con Leaflet</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<style>
#mymap { height: 400px;
width: 500px;
}
</style>
</head>
<body>
<h2>La mia prima mappa con Leaflet</h2><
<!-- contenitore della mappa -->
<div id="mymap"> </div>
...
...

Notare che il blocco <div id=mymap> è vuoto, cioè dentro non dobbiamo scrivere nulla.
Aggiungiamo ora (nel <body> dopo il <div id=mymap> … </div>) lo script che ci serve per caricare ed inizializzare la mappa che vogliamo visualizzare e che nella sua forma più semplice (con opzioni elementari) sarà così:
<script>
var map = L.map('mymap').setView([43.1045, 12.3895], 13);
//carica e inizializza la mappa base
var OSM_layer =L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
{attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a>'}).addTo(map);
</script>

Qui troviamo i primi oggetti (classi) definiti nella libreria di Leaflet; vediamo di capire cosa sono e a che servono.

Per la documentazione completa delle API di Leaflet con la spiegazione di classi, proprietà e metodi, vi consiglio di consultare sempre la documentazione ufficiale: leafletjs.com/reference.html.

Naturalmente il tutto è scritto nella sintassi tipica del linguaggio JavaScript, ma non starò qui a spiegarvi anche questa (… ve l’ho detto prima che avere delle conoscenze, almeno di base, di HTML, CSS e JavaScript serve !).

Lo script crea la variabile “map” e gli assegna un nuovo oggetto L.map a cui passa l’id dell’elemento <div> in cui deve essere contenuta la mappa (nel nostro caso “mymap”); dopodichè vengono definite alcune sue opzioni col metodo setView che sono : 
le coordinate del punto centrale dell’area geografica che vogliamo visualizzare: [43.647, -79.394]; 
il suo livello di zoom iniziale: 13. 

Quindi dobbiamo dire il tipo di mappa base che vogliamo visualizzare, o per usare un linguaggio più tecnico, il “map provider” che ci fornisca le “tiles” della mappa che desideriamo. Ciò viene fatto definendo l’oggetto L.tileLayer e impostando qual’è il map-provider (nel nostro esempio è OSM: ‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’). Poi viene anche definita una sua opzione chiamata “attribution” che è un semplice testo per descrivere l’origine della mappa ed altre eventuali informazioni su copyright o licenze d’uso; esso verrà visualizzato nell’angolino in basso a destra della mappa.

Infine all’oggetto L.tileLayer viene applicato il metodo addTo(map) che serve per aggiungere tale layer alla nostro oggetto “map”.

Grazie alla versatilità della sintassi di JavaScript, lo stesso script può essere riscritto nel seguente modo che, a secondo dei gusti, può risultare più chiaro da comprendersi; ma il risultato ovviamente non cambia.

<script>
var map = new L.Map('mymap');
var url = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png';
var attrib = '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors';
var mylayer = new L.TileLayer(url, {attribution: attrib});
map.setView([43.1045, 12.3895],13)
map.addLayer(mylayer);
</script>

Con i dati di esempio che abbiamo usato, la mappa visualizzata nella nostra pagina HTML sarà la seguente :
Lealflet OSM Perugia
Essa è già comprensiva della funzione “zoom” azionabile con i bottoni +/- o con la rotellina del mouse. Potete divertirvi a cambiare le dimensioni del riquadro-mappa, o le coordinate del suo centro (basta che siano coordinate valide) o il livello di zoom e vedere che cosa succede.
Map providers e coordinate del centro mappa


Ma ci chiediamo ora: se si vuole cambiare il tipo di base-map visualizzato e quindi il map-provider e/o la zona geografica che ci interessa e quindi le coordinate del centro mappa, dove reperiamo queste informazioni ?

Per quanto riguarda la scelta del tipo di mappa, si può visitare questo sito: leaflet-providers/preview, in cui sono elencati e visualizzabili in preview tutti i map-providers disponibili per Leaflet. Sulla destra si possono scorrere e scegliere le diverse mappe, tra cui ci sono anche quelle tradizionalmente usate per Leaflet (OSM e Mapbox).

Una volta scelta una mappa, oltre a vederla visualizzata per intero nella pagina, in alto compare anche un riquadro che mostra il suo nome ed il codice JavaScript (URL e attribution) che va indicato nell’oggetto L.tileLayer per identificarla; non dobbiamo fare altro che copiarlo e poi incollarlo nel nostro codice.
leaflet-provider preview
Per quanto riguarda le coordinate del centro mappa, queste sono coordinate geografiche (latitudine, longitudine) espresse nel sistema WGS84 in formato decimale. Se non conosciamo le coordinate dell’area che ci interessa rappresentare, possiamo recuperarle usando Google Maps oppure OSM; con entrambi il modo di farlo è simile.


Con Google Maps, una volta individuato sulla mappa il punto centrale che interessa, basta cliccarci sopra e si aprirà in basso una finestrella in cui vengono mostrate anche le sue coordinate; queste sono quelle da ricopiare ed inserire in setView.

coordinate google maps
Con OSM (OpenStreetMap) invece, dobbiamo muovere la mappa in modo che il punto centrale che ci interessa ricada più o meno a centro; dopodichè si clicca su “dove sono” (nella casella “cerca”). In risposta avremo, anche in questo caso, una serie di informazioni, tra cui appunto le coordinate del punto.













Aggiungere più layers

Sappiamo bene che spesso è utile avere una mappa costituita da più layers sovrapposti; grazie alla trasparenza o meno di alcune zone di un layer, è possibile intravedere anche il layer sottostante e quindi avere un risultato visivo che è la somma dei diversi layers. In altri casi i layers sono completamente opachi (base maps) e quindi necessita un “selettore” per scegliere di volta in volta quale layer si vuole visualizzare.

Aggiungere più layers in Leaflet è molto semplice: basta aggiungere un comando L.tileLayer( ….).addTo(map) per ogni layer che si vuole sovrapporre e la sovrapposizione avverrà nell’ordine in cui essi si susseguono, cioè l’ultimo è quello sopra a tutti.

Usando sempre il nostro esempio di prima, aggiungiamo un altro layer (fornito dal map provider CartoDB), che contiene solo delle etichette, nel seguente modo :

<script>

var map = L.map('mymap').setView([43.1045, 12.3895], 13);

//layer inferiore

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {

attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'

}).addTo(map);

//layer superiore

L.tileLayer('http://{s}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}.png', {

attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'

}).addTo(map);

</script>

Essendo questo secondo layer trasparente (tranne l’etichette) il risultato è il seguente:

osm_perugia_label

leaflet selettore layer
Qui potete vedere l’esempio (click sul bottone) completo funzionante:
webmap esempio
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>La mia prima mappa con Leaflet</title>
  <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
  <script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
  <style>
      html, body {
       height: 100%;
       font-family: arial;
       font-size: 12px;
      }
      #mymap {
        height: 600px;
        width: 600px;
      }
      @media (max-width: 600px) {
        .foothead, #mymap {width: 100%;};
      }
   </style>
</head>
<body>
<center>
<img class="foothead" src=./images/barra_logo_600.jpg border=0>
<h2>La mia prima mappa con LeafletJS</h2>
<h3>Definizione della mappa base e selezione dei layers</h3>
<!-- contenitore della mappa -->
<div id="mymap"></div>
<br><br>
<hr class="foothead" size=3 color=#000080 width=600>
<table width=600 class="foothead"  style="font-size:12px;">
<tr><td width=50%>&copy; 2015 - www.geomappando.com</td>
<td align=right>e-mail: <a href="mailto:info@geomappando.com">info@geomappando.com</a></td></tr></table>
<br><br>
</center>

<script>
 var map = L.map('mymap').setView([43.1045, 12.3895], 13);

 <!-- 1^ base map -->
 var OSM_layer =L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a>'
 });

<!-- 2 base map -->
var Esri_WorldStreetMap = L.tileLayer
('http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {attribution: 'Tiles &copy; Esri &mdash; Source: Esri'
});

<!-- layer trasparente -->
var CartoDB_label = L.tileLayer('http://{s}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}.png', { attribution: '&copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
 })

<!-- array delle mappe base -->
var baseMaps = {
 "OSM": OSM_layer,
 "ESRI": Esri_WorldStreetMap
};

<!-- array dei layer trasparenti -->
var overlayMaps = {
 "Label": CartoDB_label
};

<!-- carico la mappa base di default -->
OSM_layer.addTo(map);

<!-- attivo il selettore di layers -->
L.control.layers(baseMaps,overlayMaps).addTo(map);

</script>

</body>
</html>

Aggiungere markers e popups


Ulteriori elementi di base che possiamo aggiungere alla nostra mappa sono : 
i markers: marcatori o segna-posizione che individuano e segnalano un preciso punto sulla mappa; 
i popups: finestrelle che appaiono cliccando su un marker per mostrare delle info riguardanti il dato punto. 

Aggiungere un marker (col simbolo di default) a una mappa è molto semplice; basta conoscere le coordinate (Lat, Long in WGS84) del punto che deve segnalare e poi usare l’oggetto L. marker per definirlo ed il metodo addTo(map) per aggiungerlo nella mappa. Qui vediamo per esempio il codice per l’aggiunta di tre marker :
<script>

var map = L.map('mymap').setView([43.1045, 12.3895], 13);

//base map

var OSM_layer =L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a>'

}).addTo(map);

//definizione e aggiunta dei markers

var marker1 = L.marker([43.1247, 12.3966]).addTo(map);

var marker2 = L.marker([43.1161, 12.3867]).addTo(map);

var marker3 = L.marker([43.1021, 12.3893]).addTo(map);

</script>



Se invece vogliamo aggiungere un marker che abbia un simbolo a nostra scelta diverso da quello di default, allora dobbiamo definire un oggetto L.icon che descriva il simbolo (icona/immagine) che vogliamo usare; innanzitutto : la sua posizione (URL) e le sue dimensioni. L’icona da usare, può essere sia in locale (in una nostra cartella immagini) che in remoto su un sito che le renda disponibili on-line. Il tipo di immagine può essere qualsiasi (jpg, gif, svg, .. etc), anche se in genere si preferiscono le SVG (Scalable Vector Graphics) in quanto si possono ingrandire/ridurre senza perdere di qualità. Poi usando L.marker , oltre a definire le sue coordinate sulla mappa, useremo anche l’attributo opzionale icon che serve appunto per indicare quale immagine usare per rappresentarlo.


Allora partendo dall’esempio precedente, se ai precedenti tre markers di default ne aggiungiamo un’altro che usa una immagine “pin_red.svg” (messa nella cartella “images”), il codice Javascript da accodare è il seguente:

//definizione immagine/icona

var pin_red = L.icon({

iconUrl: './images/pin_red.svg', // posizione

iconSize: [48, 48], // dimensioni

});

//definizione marker con icona personalizzata

var marker4=L.marker([43.1116, 12.3774], {icon: pin_red}).addTo(map);

</script>

il risultato complessivo è il seguente :

leaflet markers
QQuando definite un marker esso di default è “clickable”, ovvero, a meno di non annullare esplicitamente questo comportamento (impostando clickable: false), quando ci passate sopra col mouse, il cursore si trasforma in “dito puntato” per effettuare un click; il che implica una qualche azione.

Una di queste possibili azioni e l’apertura di un finestrella “popup” che contiene delle informazioni riguardanti il punto segnalato dal marker o un qualunque altro avviso vogliate visualizzare. Notare che il testo del popup può essere scritto usando la formattazione HTML.

Per associare un popup ad un marker (col simbolo di default o con icona personalizzata) basta usare il metodo .bindPopup e in esso specificare il testo che si vuole compaia; ecco come :


L.marker([43.6470, -79.3942]).bindPopup('Testo da mostrare dentro il popup').addTo(map)

oppure, usando più istruzioni separate per ogni metodo:

var my_marker = L.marker([43.6470, -79.3942]);

my_marker.bindPopup('Testo da mostrare dentro il popup');

my_marker.addTo(map);

Riprendendo il nostro esempio con 4 markers, scegliamo di rendere il primo no-clickable (quindi non prevediamo un popup) e per gli altri aggiungiamo dei popups che semplicemente descrivono la località su cui puntano; il codice completo diventa allora così:


<script>
var map = L.map('mymap').setView([43.1045, 12.3895], 13);
//base map
var OSM_layer =L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a>'
}).addTo(map);

//definizione dei markers di default con relativo popup
var marker1 = L.marker([43.1247, 12.3966], {clickable: false});
var marker2 = L.marker([43.1161, 12.3867]).bindPopup('<b>Marker2</b>:<br>Università di Perugia');
var marker3 = L.marker([43.1021, 12.3893]).bindPopup('<b>Marker3</b>:<br>Parco Sant\'Anna');
//aggiunta marker nella mappa
marker1.addTo(map);
marker2.addTo(map);
marker3.addTo(map);

//definizione immagine/icona
var pin_red = L.icon({
iconUrl: './images/pin_red.svg', // posizione
iconSize: [48, 48], // dimensioni
});

//definizione marker con icona personalizzata e relativo popup

var marker4 = L.marker([43.1116,12.3774], {icon: pin_red}).bindPopup('<b>Marker4</b>:<br>Supermercato CONAD');

<!-- aggiunta marker personalizzato nella mappa -->

marker4.addTo(map);
</script>


Per vedere questo esempio funzionante cliccate qui:
webmap esempio
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
  <title>La mia prima mappa con Leaflet</title>
  <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
  <script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
  <style>
      html, body {
       height: 100%;
       font-family: arial;
       font-size: 12px;
      }
      #mymap {
        height: 600px;
        width: 600px;
      }
      @media (max-width: 600px) {
        .foothead, #mymap {width: 100%;};
      }
   </style>
</head>
<body>
<center>
<img class="foothead" src=./images/barra_logo_600.jpg border=0>
<h2>La mia prima mappa con LeafletJS</h2>
<h3>Definizione di markers e popups</h3>
<!-- contenitore della mappa -->
<div id="mymap">  </div>
<br><br>
<hr class="foothead" size=3 color=#000080 width=600>
<table width=600 class="foothead"  style="font-size:12px;">
<tr><td width=50%>&copy; 2015 - www.geomappando.com</td>
<td align=right>e-mail: <a href="mailto:info@geomappando.com">info@geomappando.com</a></td></tr></table>
<br><br>
</center>

<script>
 var map = L.map('mymap').setView([43.1045, 12.3895], 13);

 <!-- base map -->
 var OSM_layer =L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a>'
 }).addTo(map);

 <!-- definizione dei markers di default con relativo popup-->
 var marker1 = L.marker([43.1247, 12.3966], {clickable: false});
 var marker2 = L.marker([43.1161, 12.3867]).bindPopup('<b>Marker2</b>:<br>Universita'  di Perugia');
 var marker3 = L.marker([43.1021, 12.3893]).bindPopup('<b>Marker3</b>:<br>Parco Sant\'Anna');

 <!-- aggiunta marker nella mappa -->
 marker1.addTo(map);
 marker2.addTo(map);
 marker3.addTo(map);

 <!-- definizione immagine/icona -->
 var pin_red = L.icon({
 iconUrl: './images/pin_red.svg', // posizione
 iconSize: [48, 48], // dimensioni
 });

 <!-- definizione marker con icona personalizzata e relativo popup -->
 var marker4 = L.marker([43.1116,12.3774], {icon: pin_red}).bindPopup('<b>Marker4</b>:<br>Supermercato CONAD');
 <!-- aggiunta marker personalizzato nella mappa -->
 marker4.addTo(map);

</script>

</body>
</html>

Bene, abbiamo visto solo alcuni degli elementi elementari per realizzare una semplice mappa con Leaflet, perchè anche mantenendoci su un livello di base, gli strumenti e le opzioni rese disponibili da Leaflet sono davvero tanti. Ma d’altra parte lo scopo di questo articolo era quello di dare un spunto per chi vuole iniziare e quindi aggiungendo altro si sarebbe corso il rischio creare confusione.

Per chi vuole, le risorse sul web per approfondire l’uso di Leaflet certamente non mancano (innanzitutto il sito ufficiale) e noi stessi ne torneremo a parlare in altri articoli. A presto !


Commenti

Post popolari in questo blog

Simulazioni di reti (con Cisco Packet Tracer)

Esercizi sulla rappresentazione della virgola mobile IEEE 754 (Floating Point)