Leaflet - sggtgi/webdev GitHub Wiki
Leaflet ist eine open-source JavaScript library zur Erstellung interaktiver Karten. Hier findet ihr ein gutes Tutorial für Einsteiger in dem die notwendigen Schritte zur Vorbereitung der Seite und das Hinzufügen von Elementen zur Karte kurz erklärt werden. Die Schritte werden im Folgenden aber mit für uns interessanten Inhalten erläutert.
Außerdem findet ihr auf den Seiten auch die Leaflet Dokumentation. Diese kann sehr hilfreich sein, wenn man Einstellungen und Verhalten von Funktionen nachschauen oder anpassen möchte und ist für die meisten "guten" libraries vorhanden.
Libraries werden wie eigene Skripte im head zur Webseite geladen. Dabei gibt es unterschiedliche Möglichkeiten. Erstens kann man libraries lokal oder mit Hilfe eines sogenannten package-Managers installieren und dann z.B. so
<script src="/path/to/leaflet.js"></script>
einladen. Wir nutzen aber erstmal den einfacheren Weg und laden eine gehostete Version, für die keine Installation notwendig ist. Bei Leaflet müssen dabei sowohl eine CSS als auch eine JavaScript Datei geladen werden. Das sieht dann wie folgt aus:
<head>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
</head>
Um eine Karte auf unserer Webseite anzuzeigen brauchen wir zuerst einen HTML-Container der diese enthält. Dazu wird im <body>
ein <div>
-Element hinzugefügt, das z.B. so aussehen könnte: <div id="mapid"></div>
. Der Container soll später die Karte enthalten und kann jetzt über CSS und JS Code angepasst werden. Zum Beispiel können wir die Größe der Karte mit CSS über #mapid { height: 500px; }
anpassen.
Um dem Container nun auch wirklich eine Karte zuzuweisen müssen wir diese Karte zuerst mit JS definieren.
var map = L.map('mapid').setView([51.90693, 8.37853], 14);
Damit wird die Karte initialisiert (im Container mapid). ´.setView(center, zoom)´ setzt den Ausschnitt der Karte. In diesem Fall auf die Koordinaten [51.90693, 8.37853]
(Gütersloh) und die Zoom-Stufe 14.
Nun fehlt uns aber noch die eigentliche Karte die angezeigt wird. Diese beziehen wir von OpenStreetMap mit diesem Befehl:
var osmlayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data: © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
maxZoom: 18
}).addTo(map);
In diesem Beispiel haben wir die maximale Zoom Stufe der Karte auf 18 gesetzt und den sogenannten tileLayer dann unserer Karte hinzugefügt (.addTo(map)
).
Damit hätten wir eine Webseite auf der eine interaktive Karte angezeigt wird. Jetzt soll diese aber noch mit Inhalten gefüllt werden. Ein Beispiel dafür wäre ein Marker. Die Dokumentation zu den möglichen Einstellungen eines Markers findet ihr hier. Um einen Marker auf das Städtische Gymnasium Gütersloh zu setzen könnte der Code so aussehen:
var sggt = L.marker([51.9094, 8.3785]).addTo(map);
Die entsprechenden Koordinaten können unter anderem in Google Maps ganz einfach gefunden werden, indem man einen Rechtsklick auf den Ort macht, von dem man gerne die Koordinate wissen möchte.
Um das ganze etwas interaktiver zu gestalten kann der Marker auch noch um ein Popup erweitert werden. Dazu wird mit der Funktion bindPopup(_content_)
dem Marker einfach der Inhalt zugewiesen, der beim Klicken auf den Marker erscheinen soll. Z.B.: sggt.bindPopup("Städtisches Gymnasium Gütersloh <br> Mein erster Marker!");
Der Code für eine Webseite mit einer OSM Karte und einem Marker auf der Schule könnte dann so aussehen:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<style>
#mapid {
height: 500px;
}
</style>
</head>
<body>
<div id="mapid"></div>
</body>
<script>
var map = L.map('mapid').setView([51.90693, 8.37853], 14);
var osmlayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data: © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
maxZoom: 18
}).addTo(map);
var sggt = L.marker([51.9094, 8.3785]).addTo(map);
sggt.bindPopup("Städtisches Gymnasium Gütersloh<br>Mein erster Marker!");
</script>
</html>
Nun wird es interessant, denn wir wollen dynamisch Daten von einem externen Dienst zur Karte laden. Dabei sollen Daten eines Sensors von der OpenSenseMap auf der Karte im Popup eines Markers angezeigt werden. Zunächst wird die id der Sensebox benötigt, von der die Daten geladen werden sollen. Diese findet ihr zum Beispiel in der Adresszeile eures Browsers, wenn die entsprechende Box auf der OpenSenseMap angewählt ist. Mit der Funktion fetch()
werden nun die Daten über eine Schnittstelle zur OpenSenseMap, eine sogenannte API, geladen. Dazu müsst ihr im folgenden Code _mySenseboxID_
durch die id eurer Sensebox ersetzen.
fetch(
"https://api.opensensemap.org/boxes/_mySenseboxID_?format=json"
)
.then((response) => response.json())
.then((data) => showSensebox(data));
Hier werden die Daten von der opensensemap im JSON Format abgefragt und dann an die Funktion showSensebox()
übergeben. Diese Funktion müssen wir aber erst noch definieren. Die Funktion könnte zum Beispiel so aussehen:
function showSensebox(senseboxJson) {
var mysensebox = L.marker([
senseboxJson.currentLocation.coordinates[1],
senseboxJson.currentLocation.coordinates[0]
]).addTo(map);
var sensor = senseboxJson.sensors[1];
mysensebox.bindPopup(
sensor.title +
": " +
sensor.lastMeasurement.value +
" " +
sensor.unit +
"\n" +
"Timestamp: " +
sensor.lastMeasurement.createdAt
);
}
Dabei werden im Prinzip die selben Schritte wie bereits zuvor für den Marker mit Popup durchgeführt, nur dass hier die SenseBox-Daten genutzt werden. Diese werden als senseboxJson an die Funktion übergeben und dann in der Funktion weiter verarbeitet. Beispielsweise wird, um den Marker an der selben Stelle wie die SenseBox zu erstellen, die Koordinate der SenseBox direkt aus den Daten der openSenseMap übernommen (senseboxJson.currentLocation.coordinates
). Da die Daten der OpenSenseMap alle Sensoren abdeckt suchen wir uns erstmal einen davon aus, in diesem Fall den ersten Sensor und ordnen diesen der Variablen sensor
zu (var sensor = senseboxJson.sensors[1];
). Danach wird ein Popup für den Marker erstellt, das den Namen des Sensors (sensor.title
), dessen letzte Messung (sensor.lastMeasurement.value
) und den Zeitpunkt der letzten Messung enthält (sensor.lastMeasurement.createdAt
).
Wenn ihr die Code-Blöcke von fetch()
und showSensebox()
eurem Skript hinzufügt sollte automatisch der entsprechende Marker auf eurer Karte erscheinen.