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.

Zegar analogowy w Google Maps

Ten artykuł dotyczy API w wersji 2

« powrót do listy poradników

Oczywistym zastosowaniem API Google Maps są różnorakie serwisy, integrujące dane teleadresowe, zdjęciowe itp. ze zdjęciami satelitarnymi ziemi i dokładnymi mapami. Okazuje się jednak, że przy odrobinie kreatywności można stworzyć nietypową aplikację. W tym kursie zobaczysz, jak stworzyć analogowy zegar na tle Europy.

Trochę teorii

Zegar będziemy rysować za pomocą polilinii. Wpierw jednak krótko omówię, jak będziemy wyzaczać współrzędne wskazówek.

Współrzędna środka zegara jest stała. Współrzędna wskazówki np. dla wskazówki sekundowej będzie wyznaczona następująco: wartość w sekundach pomnożymy razy 6 (by uzyskać zakres od 0 do 360, czyli miarę kąta pełnego). Jak później zobaczysz, zajdzie konieczność skonwertowania miary w kątach do miary łukowej, co robi się poprzez pomnożenie kąta w stopniach razy П/180 (PI/180). Tak uzyskany kąt będzie mierzony od godziny 00:00, o czym trzeba pamiętać później. Analogicznie sprawa ma się ze wskazówką minutową.

Wskazówka godzinowa porusza się na innej zasadzie niż pozostałe. Kąt, o jaki jest odchylona od godziny 00:00 wyznaczamy następująco:

  1. dzielimy modulo godzinę przez 12
  2. tak uzyskaną wartość mnożymy przez 30, aby uzyskać zakres od 0 - 360 (pełny kąt)
  3. do wartości kąta dodajemy minuty, dzieląc je wcześniej przez 2, gdyż 1/12 tarczy zegarowej (czyli 30 stopni) odpowiada 60 minutom
  4. tak otrzymaną wartość mnożymy przez П i dzielimy przez 180, by uzyskać wartość w radianach

Jeszcze tylko rysunek poglądowy, ilustrujący kąty i interesujące nas długości:

Rysunek poglądowy

Z tego schematu jasno wynika, jak wyznaczyć wartości b i a:

  • a = c*cosβ
  • b = c*sinβ

gdzie c to promień (długość wskazówki)

Rysujemy tarczę

Tarcza będzie okręgiem z częściowo przezroczystym wypełnieniem. API nie pozwala na rysowanie okręgów wprost, ale za pomocą jednej pętli możemy to zrobić we własnym, przybliżonym zakresie:

var punkty=[];
for(i=0;i<48;i++)
{
	var kat=360*i/48;
	kat = Math.PI*kat/180;
	var srodek = mapa.fromLatLngToDivPixel(punktCentralny);
	var nowyPunktXY = new GPoint(srodek.x+180*Math.cos(kat),srodek.y+180*Math.sin(kat));
	punkty.push(mapa.fromDivPixelToLatLng(nowyPunktXY));
}
punkty.push(punkty[0]); // powielamy jeszcze raz pierwszy punkt, aby zamknąć okrąg
var poli = new GPolygon(punkty,'#555555',9,0.75,'#ffffff',0.7);
mapa.addOverlay(poli);

Najpierw tworzymy pustą tablicę, do której będziemy dodawać współrzędne. Narysujemy przybliżony okrąg za pomocą 48 odcinków (stąd 48 powtórzeń w pętli for). W każdym z powtórzeń wyznaczamy kąt, odpowiadający 1/n kąta pełnego (gdzie n to ilość iteracji, u nas 48) - wartość tę od razu zamieniamy na radiany. Następnie wyznaczamy środek, konwertując środek mapy (GLatLng) na GPoint - linia numer 6. Kolejnym krokiem jest wyznaczenie punktu na okręgu, robimy to zgodnie z zasadą, pokazaną na rysunku poglądowym, przyjmując za c 180px. Na końcu tak uzyskany punkt z powrotem konwertujemy na współrzędne geograficzne, i dodajemy do tablicy punkty.

Po wykonaniu 48 przebiegów powinniśmy mieć prawie pełny okrąg - musimy go tylko zamknąć, dodając jeszcze raz pierwszy punkt (linia 10). Następnie dodajemy polilinię z wypełnieniem na mapę.

Dodajemy kreski, oznaczające godziny

Kolejnym krokiem jest dodanie kresek, oznaczających pełne godziny. Zrobimy to na podobnej zasadzie jak rysowanie tarczy, za pomocą 12 krotnej iteracji. W każdym z powtórzeń wyznaczymy dwa punkty kreski, leżącej idealnie na średnicy okręgu:

var srodekXY = mapa.fromLatLngToDivPixel(punktCentralny);
for(var i=0; i<12; i++)
{
	var kat = 360*i/12;
	kat = Math.PI * kat / 180;
	
	var p1 = new GPoint(srodekXY.x+135*Math.cos(kat),srodekXY.y+135*Math.sin(kat));
	var p2 = new GPoint(srodekXY.x+165*Math.cos(kat),srodekXY.y+165*Math.sin(kat));
	
	var punkty = [mapa.fromDivPixelToLatLng(p1),mapa.fromDivPixelToLatLng(p2)];
	var poli = new GPolyline(punkty,'#000000',5,0.4);
	mapa.addOverlay(poli);
}

W linijce 1 wyznaczamy środek, do którego będziemy się odnosić, wyrażony współrzędnymi x i y. Następnie w pętli w każdej iteracji wyznaczamy kąt, mnożąc numer iteracji razy 360 i dzieląc przez ich ilość (12). Następnie kąt zostaje skonwertowany na wartość w radianach (linijka 5).

Punkty wyznaczamy na podobnej zasadzie, jaka była przedstawiona na rysunku poglądowym, z tą różnicą, że zamiast centralnego punktu musimy wyznaczyć początek odcinka. W powyższym przykładzie początki wszystkich kresek leżą na okręgu o promieniu 135, a ich końce na okręgu o promieniu 165. Następnie pozostaje tylko stworzenie tablicy z punktami, skonwertowanymi na wspołrzędne geograficzne, a następnie utworzenie polilinii i dodanie jej na mapę.

Rysujemy wskazówki

Podstawowym problemem i jednocześnie różnicą w stosunku do tarczy i kresek jest to, że wskazówki będą odświeżane. Musimy więc trzymać w jakiejś zmiennej globalnej odwołanie do polilinii, przedstawiającej każdą z trzech wskazówek, by móc je usuwać przy odświeżaniu. W przykładzie tym wszystkie odwołania trzymam w jednej globalnej tablicy asocjacyjnej (szczegóły w kodzie źródłowym przykładu 1. Wskazówka sekundowa będzie odświeżana co sekundę, a wskazówki minutowa i godzinowe ze względu na oszczędność i wydajność co minutę.

Aktualny czas pobieramy, tworząc obiekt typu Date. Uzyskujemy wówczas dostęp do metod getSeconds(), getMinutes oraz getHours. Kąty odchylenia od godziny zero wyznaczamy zgodnie z tym, co zostało napisane we wstępie:

var czas = new Date();
var sek = czas.getSeconds();
var min = czas.getMinutes();
var god = czas.getHours() % 12;

// obliczenia kątów:
var katMin = min*Math.PI/30;
var katSek = sek*Math.PI/30;
var katGod = (360*god/12 + min/2)*Math.PI/180;

Następnie rysujemy wskazówki na identycznej zasadzie jak kreski, tylko że tym razem już bez pętli. Przed narysowaniem trzeba usunąć starą wskazówkę za pomocą odwołania z tablicy globalnej, a potem zastąpić to odwołanie odwołaniem do nowej.

Odświeżanie wskazówki co sekundę będzie wymagało użycia funkcji setTimeout().

Całość

W tekście tym poruszyłem jedynie kluczowe zagadnienia, związane z metodą działania. Inne rzeczy, takie jak realizacja odświeżania, rysowanie wskazówek i inne drobne niuanse są wyjaśnione w komentarzach do przykładu 1, który zawiera pełny kod, i pokazuje działanie zegarka: przykład 1pokaż 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 v2

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


Dodawanie markerów przez użytkownika

API v2

Poradnik pokazuje, w jaki sposób stworzyć formularz, pozwalający na dodawanie markerów


Popularne, darmowe ikony dla markerów

API v2

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


Kategorie markerów i polilinii

API v2

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