www.gmapsapi.com

Kompleksowy kurs podstaw API, po którym mapowianie nie będzie miało przed Tobą żadnych tajemnic!

Setki przykładów, kursów i poradników z kodem gotowym do skopiowania i korzystania.

Największa strona o Google Maps API w Polsce, największe źródło informacji w języku polskim.

Pogoda na mapie

Ten artykuł dotyczy najnowszej wersji API

« powrót do listy poradników

API Google Maps oferuje nieskończenie wiele możliwości, których stosowanie jest ograniczone jedynie wyobraźnią twórcy. Są jednak elementy, których nie da się osiągnąć bez współpracy z innymi API. Serwisy, które korzystają z kilku różnych dostawców danych poprzez API nazywa się mash-upami. Najczęściej spotykane technologie w tego typu serwisach to Google Maps API, a także np. Amazon, Flickr, Youtube itp. Więcej informacji na temat mashupów pod tym adresem: http://googlepolska.blogspot.com/2007/02/co-to-jest-mashup.html.

Twój pierwszy mashup

W tej części kursu użyjemy API Google Maps oraz serwisu openweathermap.org. Na mapie Polski wyświetlimy ikonki, reprezentujące panujące w danym mieście warunki pogodowe (temperaturę, wilgotność, ikonkę itp.). W dalszej części kursu dodamy jeszcze warstwę, reprezentującą obecny układ chmur. Oto co zamierzamy osiągnąć:

Pierwszy mashup

Jak korzystać z pogody w openweathermap.org?

Jest kilka możliwych sposobów na wykorzystanie danych z serwisu pogodowego openweathermap.org. Na potrzeby tego poradnika skorzystamy z danych reprezentowanych w formacie JSON. Aby ominąć ograniczenia wynikające z pobierania plików z innego serwera (zobacz uwagi do poradnika Wczytywanie danych z pliku XML), skorzystam z pomocnej funkcjonalności oferowanej przez powyższy serwis.

API serwisu pogodowego udostępnia informacje poprzez generowany na żądanie plik JSON. Aby go wywołać, otwieramy plik http://api.openweathermap.org/data/2.5/weather?q=Warszawa,Poland&lang=pl&units=metric, gdzie parametrowi q odpowiada poszukiwana nazwa miasta lub jego współrzędne. Kliknij na powyższy adres, by przekonać się jak wygląda struktura pliku. Przykładowo, API może zwrócić:

{
   "coord":{
      "lon":21.01,
      "lat":52.23
   },
   "sys":{
      "message":0.0044,
      "country":"Poland",
      "sunrise":1384668077,
      "sunset":1384699250
   },
   "weather":[
      {
         "id":701,
         "main":"Mist",
         "description":"Mgiełka",
         "icon":"50d"
      }
   ],
   "base":"cmc stations",
   "main":{
      "temp":4.22,
      "humidity":91,
      "pressure":1018,
      "temp_min":3.33,
      "temp_max":5
   },
   "wind":{
      "speed":1.54,
      "gust":5.14,
      "deg":225
   },
   "clouds":{
      "all":88
   },
   "dt":1384679732,
   "id":756135,
   "name":"Warsaw",
   "cod":200
}

Mamy tu cały zestaw interesujących nas informacji, takich jak temperatura, wilgotność, ciśnienie a nawet obrazek! Jego nazwa jest zapisana w obiekcie weather.icon (w powyższym przykładzie 50d. Wystarczy dodać rozszerzenie .png i prefix http://openweathermap.org/img/w/ aby uzyskać jego pełny adres. Przykładowo, obrazek odpowiadający nazwie 50d to:

Ikonka pogody

Podanie atrybutu lang=pl w zapytaniu pozwoliło zwrócić polski opis pogody (w powyższym przykładzie: Mgiełka). Z kolei określenie parametru units=metric nakazuje API zwrócenie temperatur w stopniach celsjusza, prędkości wiatru w km/h itp. W przeciwnym wypadku, użyte zostaną jednostki imperialne (stopnie Fahrenheita, mile na godzinę itp.)

Ominięcie zabezpieczeń

Bezpośrednio nie jest możliwe pobranie tego pliku za pomocą funkcji Ajaxa, gdyż znajduje się w innej domenie. Aby ominąć te zabezpieczenie, wykorzystam mały trick oferowany przez producenta API. Dodanie do adresu parametru callback=nazwa_funkcji spowoduje, że dane zostaną zwrapowane jako argument funkcji o nazwie nazwa_funkcji, np.:

wyswietlPogode({
   "coord":{
      "lon":-0.13,
      "lat":51.51
   },
   "sys":{
      "message":0.2266,
      "country":"GB",
      "sunrise":1384672987,
      "sunset":1384704484
   },
   "weather":[
      {
         "id":804,
         "main":"Clouds",
         "description":"Pochmurno",
         "icon":"04d"
      }
   ],
   "base":"gdps stations",
   "main":{
      "temp":8.13,
      "pressure":1026,
      "humidity":87,
      "temp_min":7.22,
      "temp_max":8.89
   },
   "wind":{
      "speed":1,
      "deg":0
   },
   "clouds":{
      "all":92
   },
   "dt":1384679403,
   "id":2643743,
   "name":"London",
   "cod":200
});

Jest to zupełnie prawidłowy skrypt JavaScript! Jeśli więc w naszym kodzie napiszemy jednoargumentową funkcję wyswietlPogode i dołączymy powyższy skrypt, zostanie ona wywołana z pobranymi danymi pogodowymi. Sprytny sposób na ominięcie konieczności pisania własnego proxy do ajaxa.

Dane

W globalnej przestrzeni zadeklaruję stały adres, pod którym dostępne są ikonki z serwisu pogodowego:

var BAZOWY_ADRES_IKON = "http://openweathermap.org/img/w/";

W tworzonym przykładzie wyświetlimy ikonki pogodowe dla kilku predefiniowanych miejsc, tak jak w każdej prognozie pogody. Dobre rezultaty daje następujący zestaw miast (zapisany w postaci javascriptowej tablicy:

var miejsca = ['Warszawa', 'Rzeszow', 'Koszalin', 'Zielona Gora', 'Lodz', 'Krakow', 'Wroclaw', 'Poznan', 'Gdansk', 'Szczecin', 'Torun', 'Lublin', 'Bialystok'];

/* pobieramy pogodę dla wszystkich miejsc */
for(var i=0; i<miejsca.length; i++)
{
	zaladujPogode(miejsca[i]+',Poland');
}

Funkcja zaladujPogode będzie musiała wykonać wspomniany wcześniej trick - dynamicznie dołączyć skrypt z danymi z API tak, by została wykonana funkcja parsująca.

var skryptPogody = document.createElement("script");
skryptPogody.setAttribute("src", "http://api.openweathermap.org/data/2.5/weather?lang=pl&units=metric&callback=wyswietlPogode&q=" + encodeURI(adres));
skryptPogody.setAttribute("type", "text/javascript");
document.head.appendChild(skryptPogody);

Musimy oczywiście napisać funkcję do obsługi danych - jej nazwa to wyswietlPogode. Musi być dokładnie taka sama, jak parametr callback z którym wywołaliśmy skrypt powyżej.

function wyswietlPogode(danePogody) {
	var punkt = new google.maps.LatLng(danePogody.coord.lat, danePogody.coord.lon);

	var opis = null;
	if (danePogody.weather && danePogody.weather.length > 0) {

		opis = "";
		for (i = 0; i < danePogody.weather.length; i++) {

			if (i != 0)
				opis += ", ";

			opis += danePogody.weather[i].description;
		}
	}

	var ikona = BAZOWY_ADRES_IKON + danePogody.weather[0].icon + ".png";
	var temperatura = danePogody.main ? danePogody.main.temp : null;
	var cisnienie = danePogody.main ? danePogody.main.pressure : null;
	var wilgotnosc = danePogody.main ? danePogody.main.humidity : null;
	var predkosc_wiatru = danePogody.wind ? danePogody.wind.speed : null;
	var zachmurzenie = danePogody.clouds ? danePogody.clouds.all : null;

	dodajMarker(punkt, ikona, (temperatura ? temperatura + "°C" : "-"), generujZawartoscDymka(opis, temperatura, wilgotnosc, predkosc_wiatru, zachmurzenie, cisnienie));
}

Wizualizacja

Funkcja generująca opis wyświetlany w dymku wygląda następująco:

function generujZawartoscDymka(opis, temperatura, wilgotnosc, predkosc_wiatru, zachmurzenie, cisnienie) {
var opis_okno = ''+
'<div class="pogoda_dymek" style="width: 220px;">'+
	'<h3>'+opis+'</h3>'+
	'<ul>' +
		'<li><strong>temperatura</strong>: ' + (temperatura ? temperatura + '°C' : 'brak danych') + '</li>' +
		'<li><strong>ciśnienie</strong>: ' + (cisnienie ? cisnienie + 'hPa' : 'brak danych') + '</li>' +
		'<li><strong>wilgotność</strong>: ' + (wilgotnosc ? wilgotnosc +'%' : 'brak danych') + '</li>' +
		'<li><strong>zachmurzenie</strong>: ' + (zachmurzenie ? zachmurzenie + '%' : 'brak danych') + '</li>' +
		'<li><strong>prędkośc wiatru</strong>: ' + (predkosc_wiatru ? predkosc_wiatru + 'km/h' : 'brak danych') + '</li>' +
	'</ul>'+
'</div>';

return opis_okno;
}

Wygenerowane okno wyglądać będzie następująco:

Markery

Teraz trzeba zadbać o wstawienie markerów na mapę i podpięcie odpowiednich zdarzeń, by całość działała zgodnie z oczekiwaniami. Domyślne markery w Google Maps API nie posiadają jednak jednej istotnej funkcjonalności, która by się w tym momencie przydała - podpisu. Chcemy bowiem, by ikonką markera była reprezentacja obecnego stanu pogodowego, a pod nim ma się znajdować na przykład temperatura.

Problem ten można rozwiązać rozszerzając standardową klasę Marker o opisaną wcześniej funkcjonalność. Na szczęście, nie musimy wymyślać tego od nowa, gdyż istnieją gotowe, przetestowane i co najważniejsze darmowe rozwiązania. Jednym z nich jest MarkerWithLabel, dostępne pod adresem http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerwithlabel/. Wystarczy dołączyć do kodu strony skrypt:

<script src="http://gmapsapi.com/examples/127/markerWithLabel.js" type="text/javascript"></script>  

by móc korzystać z jej dobrodziejstw.

Funkcja, dzięki której dane zostaną wyświetlone na mapie będzie wówczas wyglądać następująco:

function wyswietlPogode(danePogody) {
	var punkt = new google.maps.LatLng(danePogody.coord.lat, danePogody.coord.lon);

	var opis = null;
	if (danePogody.weather && danePogody.weather.length > 0) {

		opis = "";
		for (i = 0; i < danePogody.weather.length; i++) {

			if (i != 0)
				opis += ", ";

			opis += danePogody.weather[i].description;
		}
	}

	var ikona = BAZOWY_ADRES_IKON + danePogody.weather[0].icon + ".png";
	var temperatura = danePogody.main ? danePogody.main.temp : null;
	var cisnienie = danePogody.main ? danePogody.main.pressure : null;
	var wilgotnosc = danePogody.main ? danePogody.main.humidity : null;
	var predkosc_wiatru = danePogody.wind ? danePogody.wind.speed : null;
	var zachmurzenie = danePogody.clouds ? danePogody.clouds.all : null;

	dodajMarker(punkt, ikona, (temperatura ? temperatura + "°C" : "-"), generujZawartoscDymka(opis, temperatura, wilgotnosc, predkosc_wiatru, zachmurzenie, cisnienie));
}

function dodajMarker(punkt, adresObrazka, podpis, tresc) {
            
	var marker = new MarkerWithLabel({
		title: podpis,
		position: punkt,
		icon: new google.maps.MarkerImage(adresObrazka),
		labelContent: podpis,
		labelAnchor: new google.maps.Point(22, 0),
		labelClass: "temperatura",
		labelStyle: {opacity: 0.75}
	});
	
	marker.tresc = tresc;
	marker.setMap(mapa);

	google.maps.event.addListener(marker,"click",function()
	{
		dymek.setContent(marker.tresc);
		dymek.open(mapa, marker);
	});
}

Pozostały drobnostki - odrobina CSS, by całość się ładnie prezentowała. W szczególności potrzebne jest zdefiniowane stylu dla klasy temperatura (zwróć uwagę na podświetloną powyżej linię kodu):

.temperatura
{
	text-align: center;
	padding: 2px !important;
	border: 1px solid black;			    
	background: black;
	color: white;
}

.temperatura span
{
	font-family: Verdana;
	font-size: 12px !important;
	font-weight: bold;
	color: white;
}

.pogoda_dymek
{
	font-size: 10px;
	font-family: Arial;
	color: #333;
}

.pogoda_dymek h3
{
	font-size: 14px;
	padding: 1px;
	margin: 1px;
	border-bottom: 1px dotted gray;
	color: black;
}

I to tyle! Czas na przetestowanie: przykład 1pokaż kod przykładu

Uwaga

API jest darmowe, ale ma też swoje ograniczenia. Jeśli użytkownik będzie wielokrotnie odświeżał stronę w krótkim okresie czasu, może się zdarzyć, że w ramach zabezpieczenia przed przeciążeniem serwera API nie zwróci wyników. W przypadku normalnego użycia ta sytuacja się nie zdarza, mimo to warto rozważyć możliwość cachowania wyników po stronie swojego serwera, aby odciążyć serwer producenta API.

Warstwy

Serwis OpenWeatherMap oferuje również bardzo ciekawą opcje: gotowe do użycia z Google Maps API nakładki, prezentujące różne dane pogodowe, takie jak wiatr, opady, zachmurzenie itp.

Dodawanie nakładki jest niemal identyczne z procedurą, opisaną w poradniku 124:

Adresy do poszczególnych kawałków mają następujący format:

http://tile.openweathermap.org/map/identyfikator/Z/X/Y.png

gdzie identyfikator to typ mapy, Z to poziom zoom (1-19) a X i Y to współrzędne (nie należy ich jednak mylić ze współrzędnymi geograficznymi). Współrzędne te są właściwe w lokalnym układzie odniesienia, gdzie punkt (0,0) to początek mapy, a kolejne całkowite wartości to kolejne numery kafelków.

Dostępne są następujące tryby:

Zachmurzenie (identyfikator = clouds)

clouds

Opady (identyfikator = precipitation)

precipitation

Ciśnienie (identyfikator = pressure)

pressure

Prędkość wiatru (identyfikator = wind)

wind

Temperature (identyfikator = temp)

temp

Opady śniegu (identyfikator = snow)

snow

W przykładzie 2 pokazałem, jak dodać warstwę chmur przykład 2pokaż kod przykładu

Kluczowe kawałki kodu:

var mapaZachmurzenia = new google.maps.ImageMapType({
	getTileUrl: function (wspolrzedne, zoom) {
		return "http://tile.openweathermap.org/map/clouds/" + zoom + "/" + wspolrzedne.x + "/" + wspolrzedne.y + ".png";
	},
	tileSize: new google.maps.Size(256, 256),
	isPng: true,
	name: "Zachmurzenie",
	maxZoom: 19
});

oraz

mapa.overlayMapTypes.push(mapaZachmurzenia);

Podsumowanie

Korzystając z API Google Maps, z łatwością możemy tworzyć serwisy agregujące dane z wielu miejsc. W tym poradniku pokazano, jak dodać dane pogodowe oraz nowe warstwy - nakładki - na obecne w API standardowe tryby map.

Uaktualnienie

Google Maps API posiada teraz wbudowaną możliwość wyświetlania pogody i warstwy z chmurami.

biblioteka weather

Aby to zrobić, należy zmodyfikować adres skryptu poprzez dołączenie nazwy biblioteki weather:

<script src="http://maps.google.com/maps/api/js?sensor=false&amp;libraries=weather" type="text/javascript"></script>    

A następnie już w kodzie javascript:

var warstwaPogody = new google.maps.weather.WeatherLayer({
	temperatureUnits: google.maps.weather.TemperatureUnit.CELSIUS
});
warstwaPogody.setMap(mapa);

var warstwaChmur = new google.maps.weather.CloudLayer();
warstwaChmur.setMap(mapa);

Rezultat:przykład 3pokaż kod przykładu

Polecane artykuły

Dodaj stronę do ulubionego serwisu społecznościowego

Oto, co najczęściej czytają internauci, którzy przeczytali ten artykuł:

Dodawanie znaczników na mapę

API v3

Kurs podstaw cz. II: Podstawowe informacje na temat wstawiania markerów (znaczników)


Kategorie markerów i polilinii

API v3

Stwórz markery/polilinie w kilku kategoriach, a następnie ukrywaj i pokazuj wybrane kategorie


Wyświetlanie lokalizacji użytkownika

API v3

Poradnik pokazujący jak wykryć gdzie znajduje się obecnie użytkownik


Popularne, darmowe ikony dla markerów

API v3

Kurs podstaw cz. IV: Lista darmowych ikon do wykorzystania w Twojej aplikacji mapowej