Quantcast
Channel: webdesign-bamberg.net » Wetter
Viewing all articles
Browse latest Browse all 2

Erstellen einer Wetterkarte mit Hilfe des yr.no XML-Service und JQuery

$
0
0

Den Anstoss für die Neuauflage einer interaktiven Wetterkarte gab mir vor einiger Zeit ein User, der mich auf den kostenlose XML-Wetterdatenservice des Meteorologischen Instituts Norwegen auf der Seite yr.no  hinwies. Nach kurzer Recherche hörten sich für mich die Vorteile gegenüber  des wetter.com – Api recht überzeugend am: Es gibt weder ein Beschränkungs-Limit für Request-Anfragen noch benötigt man für die Anwendung einen zugehörigen Api-Key.
Am Beispiel einer Wetterkarte von Bayern möchte ich Euch im folgenden Artikel die XML-Schnittstelle sowie den Umgang mit den gelieferten Daten vorstellen.

1.  Funktionen, Aufbau und Struktur: Verwendung von Ajax / JQuery

Der Aufbau und das Zusammenspiel der einzelnen Dateien sind relativ schnell erklärt: In eine einfache HTML- Basisdatei (weathermap.html) sollen über einen assychronen Ajax-Aufruf die Wetterdaten/Symbole geladen und auf der Karte platziert werden. Dieses Daten werden dabei von einem PHP-Skript (forecast.php) bereitgestellt, das die XML-Files der jeweiligen Städte ausliest und an die HTML-Datei zurückgibt.

Dieser Aufbau hat den Vorteil, dass die komplette Seite bei einem Wechsel des Vorhersagezeitpunkts nicht neu geladen werden muss und die Karte sich somit relativ unproblematisch in bestehende Websites integrieren lässt. Über eine Navigationsleiste am Fuss der Karte kann das Wetter zum jeweiligen Vorhersagezeitpunkt angezeigt werden.

Da beim Betätigen der Vorhersage-Navigation der Ajax-Request ausgelöst, alte Daten von der Karte gelöscht, neue hinzugefügt und somit die HTML-Struktur manipuliert werden muss, benötigen wir ferner ein Javascript. Was läge bei dessen Erstellung, schon allein aus Gründen der Effizienz (manche würden es auch Bequemlichkeit nennen)  näher, als auf jQuery-Allmächtig zurückzugreifen?!

Um die Karte abzurunden und etwas subtiler zu gestalten, verwende ich im Beispiel unterschiedliche Kartentypen für Tag und Nacht. Zudem sind die Städte auf der Karte mit einem Mouseover-Effekt ausgestattet, so dass sich beim Darübergleiten mit der Maus ein Tooltip-Fenster mit näheren Wetterdaten öffnet. Auch soll das Datum und der Zeitraum des Vorhersagepunktes auf der Map ausgegeben werden.

2. Vorbereitung / Material

-Kartenmaterial: Kommerziell kostenlos nutzbares und optisch ansprechendes Kartenmaterial ist im Web leider immer noch schwer zu finden. Falls euch kein Kartenmaterial vorliegt und ihr die Wetterkarte selbst erstellen und dem Layout Eurer Seite anpassen möchtet, sucht in der Google Bilder-Suche zunächst nach einer möglichst einfarbigen Karte der dazustellenden Region. Öffnet die Karte in einem Bildbearbeitungsprogramm und erzeugt einen Pfad oder eine Auswahl um die Region und füllt diese mit entsprechender Vordergrundfarbe.

Im Beispiel verwende ich:

Wetterkarten

- Icons: Im Beispiel verwende ich ausschließlich die Wettericons von yr.no. Einen Überblick über alle Wettersymbole findet Ihr auf dieser Seite.
- Wer nachschlagen und vergleichen möchte, hier der Link zum alten ArtikelErstellen einer Wetterkarte mit Hilfe des Wetter.com-Api .

3. Erstellen der HTML-Basisdatei

Beginnen wir also mit der Erstellung der Erstellung der HTML Basisdatei, die uns als Container dient. In dieser werden die Wetterkarte, die Links zu den einzelnen Vorhersagetagen sowie die über AJAX geladenen Wetterdaten der einzelnen Städte zum jeweiligen Vorhersagezeitpunkt dargestellt. Zu Beginn binden wir im header wie gewohnt die CSS-Datei (styles.css) sowie eine aktuelle Version des jQuery Skripts ein.

HTML Datei:

<link href="css/styles.css" rel="stylesheet" type="text/css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

Für die Darstellung der Karte benötigen wir einen Div-Container (weathermap), der abhängig von der id den jeweiligen Kartentyp als Hintergrund besitzt.
In diesem befindet sich ein weiterer Div-Container (weatherdata), in den später alle Wetterdaten für die Städte geladen werden. Im Anschluss an die Wetterkarte folgt ein Div-Block (forecast_links) für die Navigation. Dieser wird mit den Links zu den einzelnen Vorhersagepunkten gefüllt.

        <div class="weathermap" id="">
		<div class="weatherdata">
			<div class="ajaxloader"></div>
		</div>
	</div>
	<div class="forecast_links"></div>

4. CSS

Die wichtigste Angabe im Stylesheet ist die Definition des Containers weathermap. Er wird im Beispiel relativ positioniert, da sich die Städteboxen später absolut an diesem orientieren sollen.
Für jede Stadt habe ich eine eigene CSS Klasse angelegt, die u.a. deren absolute Position und Breite definiert. Die Klassennamen sind bewusst gewählt und sollten eine fortlaufende Zahl enthalten. Der Grund hierfür wird später ersichtlich. Die Nummerierung muss allerdings zwingend der Reihenfolge der Städte im Array entsprechen. Da die Boxen auf einer Ebene über der Wetterkarte angezeigt werden sollen, erhalten diese zusätzlich den z-index 2.
Mit Hilfe der ids mapType_0 und mapType_1 werden die beiden Kartentypen festgelegt (Tag/Nacht).

.weathermap{
 position:relative;
 width:549px;
 height:556px;
 background-repeat:no-repeat;
 font-family:Georgia, "Times New Roman", Times, serif;
 font-size:14px;
}
#mapType_0{
    background-image:url(../img/weathermap_night.png);
}

#mapType_1{
    background-image:url(../img/weathermap.png);
}
.city_0{ /*Regensburg*/
	width:100px;
	position:absolute;
	top:190px;
	left:290px;
	z-index:2;
	text-align:center;
	}

.city_1{ /*München*/
	width:100px;
	position:absolute;
	top:345px;
	left:223px;
	z-index:2;
	text-align:center;
	}

.city_2{ /*Passau*/
	width:100px;
	position:absolute;
	top:290px;
	left:410px;
	z-index:2;
	text-align:center;
	}

.city_3{ /*Würzburg*/
	width:100px;
	position:absolute;
	top:70px;
	left:75px;
	z-index:2;
	text-align:center;
	}

.city_4{ /*Bamberg*/
	width:100px;
	position:absolute;
	top:90px;
	left:167px;
	z-index:2;
	text-align:center;
	}

.city_5{ /*Bayreuth*/
	width:100px;
	position:absolute;
	top:65px;
	left:265px;
	z-index:2;
	text-align:center;
	}

5. Javascript/JQuery

Wir definieren zunächst eine Javscript Funktion loadForecast(), bei deren Aufruf das Laden der neuen Wetterdaten initiiert wird. Als Parameter werden dieser zum einen der Vorhersagezeitpunkt als Integerwert (0., 1., 2., 3…) sowie der Kartentyp übergeben.

<script type="text/javascript">
 function loadForecast (point_of_forecast,mapType) {

    var forecastHTML; 

     $.post(

            "forecast.php", //Ajax file

            { point_of_forecast: point_of_forecast },  // create an object with all values

            //function that is called when server returns a value.
            function(data){
                forecastHTML = data.mapData;
                forecastLinksHTML = data.forecastLinks;
                initMapType =data.initMapType;

                  $('.jQuery-tooltip').remove();
                  $('.weatherdata').empty();
                  $('.weatherdata').html(forecastHTML);
                  jQuery_tooltip(".weathersymbol","jQuery-tooltip");

                  if(mapType!=2){
                  $('.weathermap').attr("id", 'mapType_'+mapType);
                  }
                  else{

                  $('.weathermap').attr("id", 'mapType_'+initMapType);

                   }

                  $('.forecast_links').empty();
                  $('.forecast_links').html(forecastLinksHTML);

            }, 

            //How you want the data formated when it is returned from the server.
            "json"
            );
     }     

</script>

Den Kern bildet ein Ajax-Request. Dabei wird die Datei forecast.php aufgerufen und dieser mittles POST-Methode der gewünschte Vorhersagepunkt übermittelt. War die Verarbeitung und die Bereitstellung der Daten durch das PHP-Skript erfolgreich, so werden die fertigen HTML-Bausteine für die Navigation und die Städteboxen zurückgeliefert und in den Variablen forecastHTML bzw. forecastLinksHTML zwischengespeichert. Anschließend beginnt die Manipulation der HTML-Struktur: Hierbei wird das div-Element mit der Klasse weatherdata zunächst geleert und die neu empfangenen Städteboxen hinzugefügt. Gleiches passiert im weiteren Verlauf auch mit der Navigation.

Zum Schluss verbinden wir noch die JS-Funktion und das HTML, indem wir sie beim ersten Laden der Seite die Function loadForecast (0,2); aufrufen. Solltet ihr euch fragen, warum als Kartenparameter “2″ definiert wurde: Die Antwort liegt darin begründet, dass, anders als beim Klick eines Links, beim ersten Aufruf des Skripts zunächst nicht bekannt ist, welcher Typ für den aktuellen Vorhersagezeitpunkt verwendet werden soll. Wurde die Wetterkarte also das erste mal aufgerufen, so wird an das PHP – Skript der Initial-Status “2″ übergeben.

<script type="text/javascript">
	function jQuery_tooltip(target_items, name){
	 jQuery(target_items).each(function(i){
			jQuery("body").append("<div class='"+name+"' id='"+name+i+"'><p>"+jQuery(this).attr('title')+"</p></div>");
			var jQuery_tooltip = jQuery("#"+name+i);

			if(jQuery(this).attr("title") != ""){ 

			jQuery(this).removeAttr("title").mouseover(function(){
					jQuery_tooltip.fadeIn(150);
			}).mouseout(function(){
					jQuery_tooltip.fadeOut(150);
			}).mousemove(function(tooltip){
					jQuery_tooltip.css({left:tooltip.pageX+15, top:tooltip.pageY+10});	
			});

			}
		});
	}

</script>

Da wir die detaillierten Wetterangaben auf der Karte mit Hilfe eines Tooltips beim Überfahren mit der Maus anzeigen möchten, habe ich bereits vorher ein fertiges Tooltip-Skript hinzugefügt, welches durch den Aufruf  jQuery_tooltip(“.weathersymbol”,”jQuery-tooltip”);  innerhalb der Methode loadForecast() initialisiert wird. Hierbei wird für alle Elemente mit der Klasse .weathersymbol ein kleine, zunächst ausgeblendet Box erstellt, deren Inhalt sich durch das title-Attribut ergibt. Damit es zu keinen Überscheidungen kommt, löschen wir auch hier bei jedem Aufruf der Funktion loadForecast() die zuvor erstellten Tooltips.

6. PHP / XML

Kommen wir nun zum letzten und zugleich kompliziertesten Teil, der unsere Wetterkarte mit Informationen füllt: dem über Ajax aufgerufenen PHP-Skript forecast.php.

Zunächst fragen wir den mittles POST übergeben Zeitpunkt ab, wandeln diesen in einen Integerwert um und legen ihn in der Variable $point_of_forecast ab. Dieser dient im weiteren Verlauf zugleich als unser Index. Anschließend definieren wir 3 Arrays:

- $cityname: Array mit den Städtenamen (die Reihenfolge richtet sich nach der Nummerierung im Klassennamen der Städte im CSS-File)
- $periods: Wie im weiteren Verlauf in der XML-Datei zu sehen sein wird,  gibt es 4 verschiedene Vorhersagepunkte (0,1,2,3) an einem Tag. Damit wir später eine Relation zwischen Vorhersagepunkt und dem dazugehörenden Namen erzielen, definieren wir ein Array, dessen Index der Reihenfolge der Vorhersagezeitpunkte und deren Werte den jeweiligen Namen der Zeitpunkte entsprechen.
- $mapTypes: Ähnlich wie zuvor machen wir uns den Index des arrays zu Nutze, um eine Beziehung zwischen Zeitpunkt der Wettervorhersage und Kartentyp zu erreichen.

if (isset($_POST['point_of_forecast'])){
    $point_of_forecast = (int)$_POST['point_of_forecast'];   
}else{
    $point_of_forecast = 0;
}

//array of cities, shown on map
$cityname=array();
$cityname[0]="Regensburg";
$cityname[1]="München";
$cityname[2]="Passau";
$cityname[3]="Würzburg";
$cityname[4]="Bamberg";
$cityname[5]="Bayreuth";

/*if cities from different countries should be shown on map, you need to set the realted countries/states 
example: 

$countries[0]="Germany";
$countries[1]="Italy";
...
$countries[0]="Bavaria";
$countries[1]="Umbria";
*/

$countries = array();
$states = array();

//translations of periods
$periods=array();
$periods[0] ="night";
$periods[1] ="morning";
$periods[2] ="afternoon";
$periods[3] ="evening";

//relation array: period<->mapType
$mapTypes =array();
$mapTypes[0] ="0";
$mapTypes[1] ="1";
$mapTypes[2] ="1";
$mapTypes[3] ="0";

/*amount of points of forecast*/
$forecastLimit=10;
$returnValuesMap="";
$returnLinks="";
$initMapType;
$length=count($cityname);
$reference_period;

Mit Hilfe der Variable $forecastLimit wird die Anzahl der Vorhersagepunkte festgelegt. Ergänzend sei an dieser Stelle erwähnt, dass man für eine größere Anzahl an Vorhersagepunkten in der HTML-Datei idealerweise auf einen content-slider oder eine drop-down box zurückgreifen sollte.

Das zentrale Element unserer php-Datei bildet nun eine for-Schleife, in der die Rückgabewerte des Ajax Aufrufs erzeugt werden. Der Programmablauf stellt sich innerhalb wie folgt dar:

- Erzeugen des XML-Requests
- Erstellen des Navigationsmenüs im ersten Schleifendurchgang
- Auslesen und Zusammensetzen der Wetterdaten

6.1  XML-Request und XML-Struktur

Zunächst muss für den jeweiligen Ort die entsprechende URL erzeugt werden, unter der die Wetterdaten im XML-Format erreichbar sind. Die URL einer gültigen Suchanfrage setzt sich nach dem Schema
http://www.yr.no/place/[Name des Landes]/[Name des Bundeslandes]/[Name der Stadt]/forecast.xml

zusammen.

Entsprechend dieser Vorgabe wird der URL-String $sSearchUrl schrittweise komplettiert. Welche Teile dabei dynamisch generiert werden müssen, hängt in erster Linie davon ab, ob sich die Orte in unterschiedlichen Ländern/Bundesländern befinden. In unserem Beispiel befinden sich alle Städte in Bayern, so dass im URL-String lediglich der Name der Stadt dynamisch ergänzt werden muss.
Um die URL zu überprüfen, kann diese in die Adresszeile des Browsers eingefügt werden. Besitzt die URL eine gültige Form, sollte die Vorhersage in einer XML-Struktur angezeigt werden. Anschließend werden mit einem verschachtelten Funktionsaufruf die Wetterdaten im XML-Format von unserem PHP-Skript angefordert.

$api = simplexml_load_string(file_get_contents($sSearchUrl));

Hinweis: Um die Funktion file_get_contents() für das Einlesen einer externen URL-Aufruf nutzen zu können, ist in den PHP-Einstellung des Webservers (PHP.ini) die Erlaubnis hierzu zwingend erforderlich (allow_url_fopen=”on“).

In der Variable $api steht uns ab diesem Zeitpunkt die kompletten Vorhersagedaten der Stadt in XML-Form zur Verfügung:

 
<weatherdata>
  <location>
    <name>Bamberg</name>
    <type>City</type>
    <country>Germany</country>
    <timezone id="Europe/Berlin" utcoffsetMinutes="60"/>
    <location altitude="264" latitude="49.87948" longitude="10.88634" geobase="geonames" geobaseid="2952984"/>
  </location>
  <credit>...</credit>
  <links>
    <link id="xmlSource" url="http://www.yr.no/place/Germany/Other/Bamberg/forecast.xml"/>
    <link id="xmlSourceHourByHour" url="http://www.yr.no/place/Germany/Other/Bamberg/forecast_hour_by_hour.xml"/>
    <link id="overview" url="http://www.yr.no/place/Germany/Other/Bamberg/"/>
    <link id="hourByHour" url="http://www.yr.no/place/Germany/Other/Bamberg/hour_by_hour"/>
    <link id="longTermForecast" url="http://www.yr.no/place/Germany/Other/Bamberg/long"/>
  </links>
  <meta>
    <lastupdate>2012-11-16T06:49:58</lastupdate>
    <nextupdate>2012-11-16T09:30:00</nextupdate>
  </meta>
  <sun rise="2012-11-16T07:30:54" set="2012-11-16T16:31:11"/>
  <forecast>
    <tabular>
      <time from="2012-11-16T10:00:00" to="2012-11-16T12:00:00" period="1">
        <!--
        Valid from 2012-11-16T10:00:00 to 2012-11-16T12:00:00
        -->
        <symbol number="4" name="Cloudy" var="04"/>
        <precipitation value="0"/>
        <!-- Valid at 2012-11-16T10:00:00 -->
        <windDirection deg="164.0" code="SSE" name="South-southeast"/>
        <windSpeed mps="2.1" name="Light breeze"/>
        <temperature unit="celsius" value="2"/>
        <pressure unit="hPa" value="1022.2"/>
      </time>
      <time from="2012-11-16T12:00:00" to="2012-11-16T18:00:00" period="2">
        <!--
        Valid from 2012-11-16T12:00:00 to 2012-11-16T18:00:00
        -->
        <symbol number="3" name="Partly cloudy" var="03d"/>
        <precipitation value="0"/>
        <!-- Valid at 2012-11-16T12:00:00 -->
        <windDirection deg="176.1" code="S" name="South"/>
        <windSpeed mps="2.5" name="Light breeze"/>
        <temperature unit="celsius" value="5"/>
        <pressure unit="hPa" value="1021.3"/>
      </time>
      ...
      ...
      ...

Der Aufbau der XML-Datei ist im Hinblick auf unser Vorhaben jedoch ein wenig problematisch: Die Vorhersagepunkte <time> sind nicht in einzelne Tage gegliedert sondern folgen in der XML-Datei fortlaufend aufeinander. Für die Navigationsleiste bedeutet das, dass wir für die Unterteilung in einzelne Tage ein kleines bisschen zusätzliche Logik benötigen, um so die Beziehung zwischen Tag und Vorhersagezeitpunkt herstellen zu können.

Jeder <time>-Knoten besitzt dabei ein Attribut period, dessen Wert die Tageszeit der Vorhersage angibt (0=Nachts, 1=Morgen, 2= Nachmittag, 3=Abend) sowie einige Kindelemente (<symbol>,<windDirection> etc.), die die eigentlichen Wetterdaten beinhalten.

6.2 Erzeugen der Navigationsleiste

Der erste Durchgang der Schleife (if($i==0)) dient uns dazu, die Navigationsleiste zusammenzufügen und in der Variable $returnLinks als String schrittweise abzulegen. In einer weiteren for-Schleife durchlaufen wir deshalb Schritt für Schritt die einzelnen verfügbaren Vorhersagepunkte (time[$j]), ermitteln das zugehörige Datum mit Hilfe der SimpleXML Notation und wandeln dies in die Form “Wochentag, Tag.Monat.Jahr” um.

$forecast_date= (string)$api->forecast->tabular->time[$j]->attributes()->from;
$tstmp=strtotime($forecast_date);
$dateOfForcast = date("D, d.m.y",$tstmp);

Da wir die Datumsangabe für jeden Tag nur einmalig ausgeben möchten, brauchen wir ein Referenzdatum das uns Aufschluss darüber gibt, ob es sich beim Vorhersagezeitpunkt um den ersten “point of forecast” am neuen Tag handelt. Sind die Datumsangaben unterschiedlich, so wird das neue Datum ausgegeben und ein Trenner (devider) zwischen beide Tage eingefügt (nicht beim aller ersten Vorhersagezeitpunkt).

if($dateOfForcast==$referenceDate){
  $dateOfForcast ="";	
  $devider="";
}
	// if referenceDate != date of current point of forecast => change of days, devider and output of date are shown
else{
  $referenceDate=$dateOfForcast;
  //no devider infront of first point of forecast
  if ($j==0){
	$devider="";	
  }
  else{
  $devider="<div class=\"devider\"></div>";
  }
}

Nachdem wir die Tageszeit (period) ermittelt haben ($period=(int)$forecasts->time[$j]->attributes()->period;) setzen wir den Link zusammen und fügen diesen an den Rückgabe-String an.

$returnLink=$devider."
<div class=\"forecast_link\"> 
            <div class=\"forecast_date\"> ".$dateOfForcast."</div>
             <div class=\"forecast_point\"><a href=\"javascript:loadForecast(".$j.",".$mapTypes[$period].")\">".$periods[$period]."</a></div> 
</div>";
 $returnLinks.=$returnLink;  

if($j==0){
      /*problematic xml structure of yr.no: the forecast of some cities start with different periods. This happens only from time to time, while yr.no is updating weather data. 
    Solution: First period of first city in array is taken as reference point. */
    $reference_period =$period;
    $initMapType=$mapTypes[$period];
 }

Wie bereits in der Beschreibung des Javscript Parts geschildert, muss der JS Funktion loadForecast() die fortlaufende Nummer für den Vorhersagezeitpunkt sowie der zugehörende Kartentyp als Parameter übergeben werden. Eigentlich wäre es das auch schon gewesen, würde der Teufel nicht im Detail stecken. Denn zwei Dinge sind noch zu erledigen:

- Da beim ersten Aufruf der Seite der Karten-Typ noch nicht bekannt ist, wird dieser in einem separaten Rückgabe-String gespeichert und an das Javscript übermittelt.
- Update Problematik von yr.no : Speichern der ersten folgenden period der ersten Stadt im array (s. nächster Punkt)

6.3 Update Problematik von yr.no

Bevor ich auf das Auslesen der Wetterdaten zu sprechen komme, möchte ich an dieser Stelle auf ein weitreichendes Problem im Umgang mit den yr.no- Wetterdaten eingehen.

Die Aktualisierung der Wetterdaten seitens yr.no für die einzelnen Standorte erfolgt nicht synchron, so dass die Vorhersagezeitpunkte sich unterscheiden können.

Folgende Konstellation der vorhanden Zeitpunkte für zwei Orte wäre während eines Update-Vorgangs denkbar:

Referenzort: 2,3,0,1,2…
Aktueller Ort: 3,0,1,2,3…

Da die Daten im aktuell betrachteten Ort bereits aktualisiert wurden, fehlen die Werte für den Nachmittag. Um dies zu umgehen, wird die erste auftretende Periode der ersten Stadt im Array wird als Refernzwert verwendet, um mögliche Abweichungen aufzudecken.

$upcoming_period = (int)$api->forecast->tabular->time[0]->attributes()->period;

		//example: the first point of forecast for Passau is afternoon, while the forecast of reference city Regensburg still starts with morning 

		if($upcoming_period!=$reference_period)
		{
			// because there are no datas for the first point of forecasts, only the name of passau is shown of the map
			if($point_of_forecast == 0){

				$returnValuesMap=$returnValuesMap."<div class=\"city_".$i."\"> 
				<div class=\"cityname\">".$cityname[$i]."</div>
				</div>";
				//setting the point of forecast to -1 (no data available), only for this city
				$point_of_forecast=-1;
			 }

			else{
				// for the 2nd, 3rd, 4th ... point of forecast, the last point of forecast is taken and $point_of_forecast decreased, only for this city
				$point_of_forecast--;
			}		
		}

Stimmen die Vorhersagezeitpunkte nicht überein, so werden diese, falls der erste “point of forecast” angefordert wurde, auf der Karte nicht ausgegeben, da dieser nicht mehr vorhanden ist. Falls es sich um den 2., 3., 4. etc. Zeitpunkt handelt, so wird der index temporär um 1 reduziert und der vorherige Vorhersagepunkt verwendet. Der Index muss nach dem Auslesen der Daten am Ende dann natürlich wieder auf den Ursprung zurückgesetzt werden.

Alternative/Hinweis:
Eine alternative Lösung dieser Problematik könnte auch darin bestehen, die XML Files der Orte Cronjob-gesteuert zu einem Zeitpunkt aufzurufen (z.B. am Abend), bei dem alle Vorhersagen mit dem identischen Vorhersagepunkt beginnen, diese auf dem Webserver zu speichern und als Vorhersagebasis zu nutzen. Das hätte zum einen den Vorteil, dass man auf das beschriebene Prozedere verzichten kann und zum anderen, dass man die in 6.1 angesprochene Beziehung zwischen Tag und Vorhersagezeitpunkt einfacher herstellen kann.

Nun hat allerdings nicht jeder Zugriff auf Servereinstellungen und/oder Cronjobs. Um euch eine allgemeine Lösung vorzustellen, habe ich auf die Cronjob Variante verzichtet. Steht die Möglichkeit einen Cronjob einzurichten zur Verfügung, würde ich eindeutig zu dieser “sauberen” Alternative tendieren.

6.4 Auslesen der Wetterdaten

Nachdem der Index $point_of_forecast im vorherigen Schritt überprüft und ggf. angepasst wurde, ist nun alles für das Auslesen der Daten vorbereitet. Wir ermitteln zunächst das Wetter, das Symbol und die Temeperatur, die in einem String eingesetzt und schließlich an dem bisherigen $returnValuesMap angehängt werden. Alle weiteren Wetterdaten (Windstärke, Windrichtung, Luftdruck) fügen wir ebenfalls zu einem String zusammen, welchen wir im title-Attribut des Bildes / der Links ausgeben.

if ($point_of_forecast!=-1){

		$weather_symbol=(string)$api->forecast->tabular->time[$point_of_forecast]->symbol[0]->attributes()->var;
		$temperature= (string)$api->forecast->tabular->time[$point_of_forecast]->temperature[0]->attributes()->value;	
		$weather_text="Temperature: ".$temperature."°C<br>";		

		$wind_direction=(string)$api->forecast->tabular->time[$point_of_forecast]->windDirection[0]->attributes()->code;
		$windSpeed =(float)$api->forecast->tabular->time[$point_of_forecast]->windSpeed[0]->attributes()->mps;
		$windSpeed = $windSpeed *3.6;

		$wind= "Wind: ".$windSpeed."km/h (".$wind_direction.") <br>";
		$weather_text.=$wind;

		$pressure = "Pressure: ".(string)$api->forecast->tabular->time[$point_of_forecast]->pressure[0]->attributes()->value. "hPa";
		$weather_text.=$pressure;

		$returnValuesMap=$returnValuesMap."<div class=\"city_".$i."\"> <div><img title='".$weather_text."' src='http://symbol.yr.no/grafikk/sym/b100/".$weather_symbol.".png' class='weathersymbol'/></div>
		<div class=\"cityname\"><a href=\"\" class=\"weathersymbol\" title='".$weather_text."' >".$cityname[$i]."</a></div><div class=\"temperature\"><div class=\"temp\">".$temperature." °C</div></div>

		</div>";

		// adding forecast date to map
		if($i==0){

			$curr_period = (int) $api->forecast->tabular->time[$point_of_forecast]->attributes()->period;

			$curr_forecast_date= (string)$api->forecast->tabular->time[$point_of_forecast]->attributes()->from;
			$curr_tstmp=strtotime($curr_forecast_date);
			$curr_dateOfForcast = date("D, d.m.y",$curr_tstmp);

			$returnValuesMap=$returnValuesMap."<div class='current_forecastdate'><span id='dayspan'>".$curr_dateOfForcast."</span><br> <span id='periodspan'>".$periods[$curr_period]."</span></div>";

		}
		//setting the point of forecast back to former value	

	$point_of_forecast = (int)$_POST['point_of_forecast'];
 }

else{	
		//setting the point of forceast back to former value	
		$point_of_forecast = (int)$_POST['point_of_forecast'];	
}

Last but not least möchten wir Datum und Zeitpunkt der Vorhersage auf der Karte ausgeben. Die Zeitangabe lesen wir beim ersten Durchgang aus der XML-Struktur, bringen diese ins gewünschte Format und hängen die erzeugte Zeichenkette ebenfalls an den Rückgabe-String. Wie bereits erwähnt korregieren wir abschließend noch den manipulierten Index, indem wir ihm wieder den ursprünglich übermittelten Wert zuweisen.

Das war’s. Das fertige Ergebnis könnt Ihr Euch nun hier ansehen und alle Meterialien und Skripte herunterladen:

Fazit:

Im Gegensatz zu wetter.com bietet yr.no derzeit eine unbeschränkte Zahl an Zugriffen. Auch Registrierung und API-Key sind nicht erforderlich. Für die Verwendung in einer Wetterkarte stellen die unterschiedlichen Aktualisierungszeitpunkte sowie die vom Anbieter etwas unglücklich gewählte XML-Struktur jedoch ein gewisses Hinternis dar. Benötigt man lediglich die Wetterdaten eines einzelnen Ortes, beispielsweise für Vorhersagediagramme und Prognosen etc., so kann die yr.no XML-Schnittstelle durchaus eine unkomplizierte und lohnende Alternative zu wetter.com sein.

The post Erstellen einer Wetterkarte mit Hilfe des yr.no XML-Service und JQuery appeared first on webdesign-bamberg.net.


Viewing all articles
Browse latest Browse all 2

Latest Images





Latest Images