Librairies carto Leaflet
La carte#
Pour créer une carte basée sur Leaflet :
- centrée sur Paris : longitude
2.35
, latitude48.85
- utilisant un élément HTML avec
id="map"
Un élément HTML + chargement des librairies (CSS + JS)
<div id="map"></div>
<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
En CSS, une hauteur à la carte
#map {
height: 500px;
}
Initialisation d’une carte Leaflet
L.map('map', {
center: [48.85, 2.35],
zoom: 13,
});
Ce que l’on note :
- utilise des factory pour créer les objets, donc sans le mot-clé
new
(ici, c’estL.map
) - la projection par défaut est EPSG:3857, mais on manipule uniquement des coordonnées en EPSG:4326
- l’ordre des coordonnées est latitude/longitude
- une carte n’a pas de couches chargées par défaut
Les projections#
Pour rappel, la projection par défaut est EPSG:3857 (Web Mercator), mais on ne manipule que des coordonnées en EPSG:4326 (WGS 84).
Pour manipuler des coordonnées dans d’autres projections, il faut alors utiliser PROJ avec le plugin Proj4Leaflet.
Les couches#
Rasters#
La principale classe est L.TileLayer
Ajout d’une couche OSM dans Leaflet
L.map('map', {
center: [48.85, 2.35],
zoom: 13,
layers: [
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}),
],
});
L’ajout de couches peut également se faire après la création de la carte avec map.addLayer(layer)
ou layer.addTo(map)
WMS#
Pour une couche WMS, c’est la classe L.tileLayer.wms
Ajout d’un flux WMS
let wmsLayer = L.tileLayer.wms("https://api.ensg.eu/geoserver/wms", {
layers: 'ensg:hydro',
format: 'image/png',
transparent: true,
tiled: true,
crs: L.CRS.EPSG4326
});
map.addLayer(wmsLayer);
Notez que le flux renvoit par défaut en EPSG:3857, mais Leaflet ne travaille qu’en EPSG:4326, il faut donc le préciser dans l’URL pour le retour avec crs: L.CRS.EPSG4326
.
Vecteurs (points, lignes, surfaces)#
L’ajout d’objets vectoriels se réalise assez simplement. Il suffit d’utiliser les fonctions L.marker
pour les marqueurs ou icônes, L.polyline
/L.polygon
pour les lignes/polygones, etc.
Leaflet
// icone sur Paris
let marker = L.marker([48.85, 2.35]);
map.addLayer(marker);
// polygon de l’ile de la cité
let polygon = L.polygon([[[48.8578,2.3393],[48.8568,2.3411],[48.8550,2.3432],[48.8534,2.3472],[48.8524,2.3497],[48.8516,2.3527],[48.8526,2.3522],[48.8538,2.3520],[48.8548,2.3510],[48.8557,2.3484],[48.8569,2.3439],[48.8573,2.3412],[48.8578,2.3393]]]);
map.addLayer(polygon);
Services web, APIs cartographiques#
La majeure partie du temps, les données affichées au sein des couches proviennent de services web géographiques ou d’APIs. Les fonds de cartes rasters par exemple sont fournis sous forme de services web (géographiques). Pour les données vectorielles, on parle le plus souvent d’APIs cartographiques (des URLs qui fournissent des données).
Voici un exemple qui affiche les tremblements de terre de plus de 4.5 sur l’échelle de Richter, sur le mois précédent.
Leaflet - Couche basée sur API en GeoJSON
let urlEarthQuakes = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_month.geojson';
fetch(urlEarthQuakes)
.then(r => r.json())
.then(data => {
L.geoJSON(data).addTo(map);
});
Il est nécessaire de faire un appel à l’API en AJAX (fetch()
), puis d’utiliser ces données avec une couche L.geoJSON
par exemple (puisque les données reçues sont en GeoJSON).
Les styles#
Styles statiques#
Style dans Leaflet
L.polygon([...], {
color: 'red',
weight: 5,
fillColor: 'blue',
fillOpacity: 0.5,
});
Pour l’utilisation d’images (pixels ou vectorielles), il faut alors référencer l’URL, et préciser les différents alignements par rapport aux coordonnées de l’objet.
Icone dans Leaflet
L.marker([...], {
icon: L.icon({
iconUrl: 'icon.png',
iconSize: [32, 32],
iconAnchor: [16, 32], // pixels
}),
});
Styles dynamiques#
Dans Leaflet, les styles dynamiques sont uniquement possibles avec un objet L.GeoJSON
. La fonction prend en paramètre l’objet (feature
).
Leaflet - Style dynamique de GeoJSON
L.geoJSON(data, {
style: function (feature) {
return {
color: feature.properties.color
};
}
})
Styles multiples#
Pas de gestion de styles multiples dans Leaflet. Si c’est nécessaire, il faut alors dupliquer les objets, et leur appliquer des styles différents, mais beaucoup d’effets graphiques sont impossibles.
Les interactions#
Avec Leaflet, les objets vectoriels étant des objets HTML et/ou SVG, il est simple de créer des interactions. Il suffit par exemple d’utiliser CSS pour modifier le style d’un élément survolé, ou d’écouter des événements JavaScript pour les autres types d’interactions.
Leaflet - Changer le style en CSS du polygon au survol
/* besoin de préciser className sur l’objet Leaflet */
.classe-polygon:hover {
fill: red;
stroke: black;
stroke-width: 10px;
}
Leaflet - Écouter le click sur un objet marker
marker.on('click', evt => {
console.log(evt.latlng);
});
Certaines interactions sont prédéfinies. C’est le cas par exemple pour déplacer les marqueurs, ou les autres objets, avec l’option draggable
ou la classe L.Draggable()
.
Leaflet - Rendre un marqueur déplaçable
let marker = L.marker([0, 0], { draggable: true });
marker.on('drag', (evt) => { });
Les popups#
Ajout d’une popup#
Si l’on souhaite ajouter une popup au click sur un marqueur, dans Leaflet, c’est assez simple. Il suffit... d’ajouter une popup. Il n’est pas nécessaire d’ajouter d’événement spécifique.
Leaflet - Ajout d’une popup
marker.bindPopup('Une popup');
Cela fonctionne également avec une couche L.geoJSON
assez simplement. Il faut alors passer une fonction, qui sera appelée pour chaque objet
Leaflet - Ajout de multiples popups
L.geoJSON(data).bindPopup(function (layer) {
return layer.feature.properties.description;
});
Modification d’une popup#
Pour modifier le contenu de la popup après sa création, il faut mettre à jour le HTML
Leaflet - Modification d’une popup
marker.on('click', evt => {
marker.getPopup().setContent('lat: ' + e.latlng.lat + ' / lng: ' + e.latlng.lng);
});