Quelle: MET Norway Weather API v.3 - Locationforecast (compact)
const response = await fetch(url);
const jsondata = await response.json();
console.log(jsondata);
Wir sehen ein GeoJSON Objekt vom Typ Point
mit Koordinaten und Seehöhe in geometry.coordinates
, Metadaten der Attribute in properties.meta
sowie den eigentlichen Vorhersagedaten im Array properties.timeseries
. Jeder Eintrag dieses Array besitzt einen Zeitstempel time
, die vorhergesagten Werte in data.instant.details
sowie Wetteraussichten mit voraussichtlichen Niederschlagsmengen für die nächsten 1, 6 und 12 Stunden in data.next_n_hours
🔗 COMMIT (dieser COMMIT enthält leider auch den, zuvor vergessenen Schritt der Plugin Konfiguration von Leaflet velocity)
Bevor wir die Wettervorhersage für den Referenzpunkt visualisieren, hängen wir außerhalb der Funktion loadWeather
das Overlay für die Wettervorhersage an die Layer control
layerControl.addOverlay(overlays.weather, "Wettervorhersage met.no");
Gleich danach defineren wir einen neuen L.circleMarker, geben ihm die vorläufigen Koordinaten [0,0]
, fügen ein Popup hinzu und hängen das Ganze an das soeben erstellte Overlay. Damit wir später auf den Marker und das Popup zugreifen können, merken wir uns den Marker in einer Variablen marker
let marker = L.circleMarker([
47.267222, 11.392778
]).bindPopup("Wettervorhersage").addTo(overlays.weather);
Leider landeten Marker und Overlay im vorhergehenden Schritt innerhalb der Funktion, weshalb eine Verschiebung des Codes vor die Funktion nötig war
Marker und Overlay sind damit verfügbar und können innerhalb der Funktion loadWeather
befüllt werden
Die Positionierung des Markers erledigt .setLatLng() für uns. Die Kordinaten entnehmen wir der Geometrie des GeoJSON-Objekts
// Marker positionieren
marker.setLatLng([
jsondata.geometry.coordinates[1],
jsondata.geometry.coordinates[0]
]);
Die aktuellen Wetterwerte finden wir im ersten Eintrag des jsondata.properties.timeseries
Array und dort in jsondata.properties.timeseries[0].data.instant.details
- ein shortcut zu diesen tief verschachtelten Details bietet sich an:
let details = jsondata.properties.timeseries[0].data.instant.details;
Danach definieren wir in einer Variablen popup
mit Template-Syntax die aktuellen Wetterwerte als ungeordnete Liste. Die Windgschwindigkeit rechnen wir in km/h um.
let popup = `
<ul>
<li>Luftdruck: ${details.air_pressure_at_sea_level} (hPa)</li>
<li>Luftemperatur: ${details.air_temperature} (°C)</li>
<li>Bewölkung: ${details.cloud_area_fraction} (%)</li>
<li>Niederschlag: ${details.precipitation_amount} (mm)</li>
<li>Relative Luftfeuchtigkeit: ${details.relative_humidity} (%)</li>
<li>Windrichtung: ${details.wind_from_direction} (°)</li>
<li>Windgeschwindigkeit: ${details.wind_speed * 3.6} (km/h)</li>
</ul>
`;
Den Popupinhalt des Markers können wir schließlich über die Methode .setPopupContent() setzen und mit .openPopup() das Popup anzeigen.
marker.setPopupContent(popup).openPopup();
Ähnlich wie beim Vorhersagezeitpunkt der ECMWF Windvorhersage, können wir auch den Zeitpunkt der Wettervorhersage bestimmen und formatieren. Wir finden das Datum für die Details des Popups im ersten Eintrag des timeseries
Arrays im Attribut time
, definieren ein echtes Datum damit und formatieren es wieder über unsere formatDate
Funktion.
let forecastDate = new Date(jsondata.properties.timeseries[0].time);
let forecastLabel = formatDate(forecastDate);
Danach können wir beim Popup eine Überschrift mit Datum ergänzen
let popup = `
<strong>Wettervorhersage für ${forecastLabel}</strong>
<!-- Liste -->
`;
Alles was wir für unser Vorhersagepopup benötigen, bekommen wir vom Locationforecast (compact) indem wir die Koordinaten LAT/LNG übergeben. Leaflet kann uns onclick
für jeden Punkt der Karte diese Werte liefern und deshalb ist es einfach, für jeden Punkt der Erde ein Popup mit der Vorhersage zu generieren. Wir müssen nur auf das Klicken auf die Karte reagieren und unsere Funktion loadWeather
mit der passenden URL füttern. In Leafletsprache sieht das (ganz am Ende des Skripts) so aus:
map.on("click", function(evt) {
console.log(evt);
});
Im Klickevent finden wir in evt.latlng.lat
und evt.latlng.lng
die Koordinaten des geklickten Punkts aus denen wir die URL für https://api.met.no/ generieren können. Der Aufruf der Funktion loadWeather
mit dieser URL platziert den Marker neu und holt sich die Vorhersage für diesen Punkt
// auf Klick auf die Karte reagieren
map.on("click", function(evt) {
let url = `https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${evt.latlng.lat}&lon=${evt.latlng.lng}`;
loadWeather(url);
});
Nachdem der timeseries
Array aus 89 Einträge in Stunden- und 6 Stundenabständen besteht, können wir die Witterungsprognose für die nächsten 24 Stunden in 3 Stundenschritten implementieren. Wir verwenden dazu jeweils das Wettersymbol in data.next_1_hours.summary.symbol_code
. Für alle dort möglichen Werte stellt uns der Locationforecast unter dem Link WeatherIcon 2.0 service passende Icons zur Verfügung, die wir uns als erstes in einem Unterverzeichnis icons/
speichern. Wir verwenden die SVG-Version da sie skalierbar ist und weniger Speicherplatz benötigt
Am Beispiel des ersten Eintrags im timeseries
Array finden wir den Dateinamen des gewünschten Symbols für die aktuelle Wetterlage im längsten verschachtelten Objekt, das wir bisher kennengelernt haben ;-) Wir speichern den Wert von jsondata.properties.timeseries[0].data.next_1_hours.summary.symbol_code
in einer Variablen symbol
und fügen ein <img> Element mit diesem Icon über +=
zum Popup hinzu. Ein style
-Attribut verkleinert die Breite des Icons auf 32px
Breite. Den Code schreiben wir direkt vor marker.setPopupContent()
// Wettericon
let symbol = jsondata.properties.timeseries[0].data.next_1_hours.summary.symbol_code;
popup += `<img src="icons/${symbol}.svg" alt="${symbol}" style="width:32px">`;
Um alle Icons der nächsten 24 Stunden in 3 Stunden Schritten anzuzeigen, können wir in einer klassischen for-Schleife
mit einer Schleifenvariable i
den timeseries
Array abarbeiten. Nach jedem Schleifendurchlauf erhöhen wir die Zählervariable um 3
(Stunden) und beenden die Schleife beim Wert 24
. Wir verpacken also den Code für unser Icon der aktuellen Wetterlage in diese for
-Schleife und ändern timeseries[0]
auf timeseries[i]
// Wettericons
for (let i=0; i <= 24; i+=3) {
let symbol = jsondata.properties.timeseries[i].data.next_1_hours.summary.symbol_code;
popup += `<img src="icons/${symbol}.svg" alt="${symbol}" style="width:32px">`;
}
Zur besseren Lesbarkeit ergänzen wir bei den Symbolen das jeweilige Datum als Tooltip über ein title-Attribut
. Das Datum finden wir in jsondata.properties.timeseries[i].time
- wir formatieren es analog zum Vorhersagezeitpunkt mit der formatdate
Funktion und setzten es als title-Attribut
beim Symbolbild ein
let forecastDate = new Date(jsondata.properties.timeseries[i].time);
let forecastLabel = formatDate(forecastDate);
popup += `<img src="icons/${symbol}.svg" title="${forecastLabel}" alt="${symbol}" style="width:32px">`;
Kosmetik: die Windgeschwindigkeit kann noch ein .toFixed(1)
vertragen
<li>Windgeschwindigkeit: ${(details.wind_speed * 3.6).toFixed(1)} (km/h)</li>