Leafletjs

Adattato da una presentazione di Maptime Milan

Sommario

  • Cos'é Leaflet.js?
  • Tutorial
Leafletjs logo

"una moderna libreria javascript open source usata per creare web-map, rilasciata nel 2011.
Per desktop e mobile, supporta HTML 5 e CSS3.
Usata da grandi siti web: Flickr, foursquare, Pinterest, craigslist, Data.gov, IGN, Wikimedia, OSM, Meetup, WSJ, Mapbox, CartoDB, GIS Cloud …
Sviluppata da Vladimir Agafonkin"

da wikipedia

vantaggi:

  • Open Source (documentazione, supporto, ...)
  • Semplice
  • Leggera
  • Flessibile (shape file, geoJson, WMS, ...)
  • etc, etc, etc, ...

TUTORIAL

Vedovelle Vs. Nasoni

Step 1
Prepariamo la pagina

Creiamo un file HTML, index.html
Carichiamo la libreria Leaflet (file con estensione .js)


<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
						
e il relativo foglio di stile (estensione .css)

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
Aggiungendo i link agli script necessari, nel <body>

Poi definiamo lo stile della pagina e della mappa (dimensioni, posizione ecc..).
all'interno dell'<header></header>, aggiungiamo il tag <style></style> in cui mettere il codice:


body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
							

Persi?
nessuna paura!

QUI un file con il codice relativo scritto fino a questo punto

Step 2
La nostra prima web-map

Definiamo il div "map", cioè la sezione della pagina web, che conterrá la nostra mappa all'interno del <body>


<div id='map'></div>

Con due righe di javascript chiediamo a Leaflet di creare una mappa dentro questo div.
Usiamo il tag <script></script> per contenere il codice javascript.


<script >
//creo una mappa con relativa posizione e zoom iniziali
var map = L.map('map').setView([41.8933439, 12.4830718], 13);

//aggiungo un layer di sfondo, o Base Layer
var baseLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
  attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http:// mapbox.com">Mapbox</a>',
	maxZoom: 18
}).addTo(map);
</script>
					
Step-2

QUI il codice index2.html

Step 3
Aggiungiamo un marker

Per inserire un punto sulla mappa, Leaflet offre il costruttore:
L.marker([lat, lng]).
Che ha bisogno di un array di coordinate
[Latitudine, Longitudine]
e dispone di metodi opzionali, come .bindPopup() per visualizzare un pop-up

Aggiungiamo quindi il codice:


// Oggetto marker
var CAEMarker = L.marker([42.63315, 11.43384])
  .bindPopup('Cittá dell´Altra Economia
Maptime!') .openPopup() .addTo(map);
Step-3

QUI il codice index3.html

Step 4
Modificare un' icona

Miglioriamo l'icona di default creando una variabile 'icona' a cui associamo un oggetto con il metodo:
L.icon()
Per saperne di più


// Icona Marker
var CAEIcon = L.icon({
	iconUrl: 'img/cae-marker.png',
	shadowUrl: 'img/cae-marker-shadow.png',
	iconSize:     [80, 80], // size of the icon
	shadowSize:   [80, 80], // size of the shadow
	iconAnchor:   [0, 0], // point of the icon which will correspond to marker's location
	shadowAnchor: [0, 0],  // the same for the shadow
	popupAnchor:  [60, 15] // point from which the popup should open relative to the iconAnchor
	});
				

La nostra icona ha due proprietà, i campi iconUrl e shadowUrl, che sono gli URL dell'immagine dell'icona e della sua ombra.
Le altre proprietà definiscono, invece, le dimensioni.

Costruito l'oggetto 'icona', possiamo ricreare il marker, ma questa volta passandogli come parametro opzionale proprio la nostra icona.


var CAEMarker = L.marker([45.448198, 9.222020],
	{ icon: CAEIcon}) // NOTA: questa opzione non era presente nello step3
	.bindPopup('Cittá dell'Altra Economia 
Maptime!') .openPopup() .addTo(map);
Step-4

QUI il codice index4.html

Step 5
GeoJSON!

Per aggiungere dati alla mappa web si utilizza il formato GeoJSON, uno standard ormai diffuso.
Esempio di GeoJSON (da geojson.org ):


{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}
				

Esistono vari modi per caricare un GeoJSON, oggi usiamo il metodo proprio di Leaflet.
Richiamiamo il file contenente i dati, con un link posto dopo quello per richiamare Leaflet:


<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<!-- Dati -->
	<script src="data/fontanelle.js"> </script>
				

Se aprite il file fontanelle.js, potete notare che il GeoJSON è stato racchiuso nella variabile fontanelle.
In questo modo, è possibile passare tutti i dati come unico parametro alla funzione L.geojson() che costruirà il Feature Layer:


// Dati GeoJSON
	var fontane = L.geoJson(fontanelle, {
		pointToLayer : function  (feature, latlng) {
			lat = feature.geometry.coordinates[0];
			lng = feature.geometry.coordinates[1];
			return L.marker([lng,lat]).bindPopup("Andiamo a bere al Bar del Drago Verde!");
		}
	}).addTo(map);
				

Nella funzione L.geojson() le singole features, di cui si compone l'insieme di dati, vengono passate a pointToLayer(). Perchè, a differenza di altre geometrie come linee e poligoni, Leaflet per i punti disegna sempre dei marker.
Per saperne di più

Step-5

QUI il codice index5.html

Step 6
GeoJSON pt.2

Analogamente a quanto fatto per un singolo marker, per modficare l'aspetto dei nasoni, basta creare una variabile con l'icona che preferite.


// Icona GeoJSON
var fontanella = L.icon ({
	iconUrl: 'img/nasone.png',
	shadowUrl: 'img/nasone-shadow.png',
	iconSize:     [80, 93], // size of the icon
	shadowSize:   [80, 93], // size of the shadow
	iconAnchor:   [0, 0 ], // point of the icon which will correspond to marker's location
	shadowAnchor: [0, 0],  // the same for the shadow
	popupAnchor:  [45, 10] // point from which the popup should open relative to the iconAnchor
});
			

..e passarla come parametro alla funzione L.marker()


// Dati GeoJSON
var fontane = L.geoJson(fontanelle, {
	pointToLayer : function  (feature, latlng) {
	lat = feature.geometry.coordinates[0];
	lng = feature.geometry.coordinates[1];
	return L.marker([lng,lat],
	{icon: fontanella}) // NOTA: questa opzione non era presente prima
	.bindPopup("Andiamo a bere al Bar del Drago Verde!");
	}
	}).addTo(map);
			
Step-6

QUI il codice index6.html

Step 7
Layers Control

Dopo aver visualizzato i dati sulla mappa; diamo la possibilità all'utente di poterli accendere e spegnere o di cambiare la base map (Base Layer).
Per farlo, aggiungiamo un piccolo menù che controlla visibilità dei Base Layers e Feature Layers.
Per far ciò, creiamo nuove variabili a cui associare i layer di sfondo:


// Mapbox Streets
//---------------
var mapboxTilesStreet = L.tileLayer('https://{s}.tiles.mapbox.com/v3/examples.map-i86nkdio/{z}/{x}/{y}.png', {
	attribution: '<a href="http://www.mapbox.com/about/maps/" target="_blank">Terms &amp; Feedback</a>'
	})

// Mapbox Medieval
//---------------
var mapboxTilesMedieval = L.tileLayer('https://{s}.tiles.mapbox.com/v3/spatial.b625e395/{z}/{x}/{y}.png', {
	attribution: '<a href="http://www.mapbox.com/about/maps/" target="_blank">Terms &amp; Feedback</a>'
	});
			

N.B. per questi due layer non abbiamo usato il metodo .addTo(map) per aggiungerli al <div id='map'>
questo perchè vogliamo dare la possibilità di accenderli solo in un secondo momento, e uno alla volta, grazie al menù.

Per questo, costruiamo due oggetti in cui salvare i riferimenti ai BaseLayers ed ai FeatureLayers, e che passeremo poi alla funzione L.control.layers() per la creazione del menù.


// Creo due oggetti con i riferimenti rispettivamente ai BaseLayers ed ai FeatureLayers
	var baseMaps={
		"Sfondo OSM": baseLayer,
		"Sfondo Mapbox Streets": mapboxTilesStreet,
		"Sfondo Mapbox Medieval": mapboxTilesMedieval
	};
	var featureLayers={
		"Nasoni": fontane,
		"CAE" : openDotMarker
	};
// Creo i controlli
	L.control.layers(baseMaps, featureLayers).addTo(map);
			
Step-7

QUI il codice index7.html

Step 8
Plugins: Marker Cluster

Altro grande vantaggio di Leaflet sono gli innumerevoli plugins sviluppati dalla comunità.
Ad esempio, vediamo come installare ed utilizzare il plugin MarkerClusterer che aggrega le fontanelle in cluster, al variare del livello di zoom.

Come prima cosa aggiungiamo il link della libreria leaflet.markercluster alla pagina, come qualsiasi altro script js:


<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<!-- leaflet.markercluster -->
<link rel="stylesheet" href="js/leaflet.markercluster/MarkerCluster.css" />
<link rel="stylesheet" href="js/leaflet.markercluster/MarkerCluster.Default.css" />
<script src="js/leaflet.markercluster/leaflet.markercluster-src.js" ></script>
<script src="js/leaflet.markercluster/leaflet.markercluster.js" ></script>
<!-- Dati -->
<script src="data/fontanelle.js"> </script>
			

Poi, seguendo la documentazione, creiamo un nuovo oggetto MarkerClusterGroup, a cui passiamo le features del layer fontane e aggiungiamolo alla mappa.


var markers = new L.MarkerClusterGroup();
	markers.addLayer(fontane);
//... Add more layers ...
map.addLayer(markers);
			

Attenzione! L'ultimo passaggio è ora togliere il metodo addTo(map) da L.geojson(fontane), altrimenti finirei con il caricare due volte lo stesso layer (uno all'inzio uso il GeoJSON per creare il layer di fontanelle, ed uno ora tramite markerClusterer)

Step-8

QUI il codice index8.html