Adattato da una presentazione di Maptime Milan
"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:
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%; }
QUI un file con il codice relativo scritto fino a questo punto
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 © <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>
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);
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);
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ù
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);
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 & 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 & Feedback</a>'
});
.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);
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)