Beipiel 5
Verwendung der asynchronen Funktionen des Google Maps
API's mittels Callback-Funktionen, Verwendung des Geocoders und des Elevation-Service
Die Arbeitsweise des Google Maps
API's wurde in Version 3 konsequent asynchron gestaltet. Es fängt damit an, dass sogar das komplette
API asynchron geladen werden kann:
Code:
http://maps.google.com/maps/
api/js?sensor=true_or_false&callback=FunctionXYZ
Nachdem alle Module von den Google-Servern geladen wurden, ruft das
API die angegebene (JavaScript-)Callback-Funktion auf.
Die ganze Umsetzung - angefangen bei der Bereitstellung der JavaScript-Funktion bis hin zum Aufruf der gewünschten Delphi-Methode - wird vom Framework übernommen. Dem eigentlichen Delphi-Quelltext sieht man die Komplexität dieses Vorganges gar nicht mehr an:
Delphi-Quellcode:
procedure TForm1.FormShow(Sender: TObject);
begin
WebBrowser1.Navigate('
about:blank');
Script:=TScript.Create(WebBrowser1);
//Skript-Objekt erstellen
with Script
do
begin
LoadBrowserFromSource(WebBrowser1,
//leere Seite:
HTMLPage(false,
//- OHNE Google Maps API
false,
//- OHNE GPS-Sensor
'
div_map'),
//- MIT Div-Container für die Karte
true);
//warten, bis die leere komplett geladen wurde
LoadAPIAsync(false,OnAPILoaded);
//Google Maps-API asynchron laden; Parameter: kein Sensor, Callback-Methode
end;
end;
procedure TForm1.OnAPILoaded;
begin
//z.B. Karte erstellen
end;
Wie wäre es aber in dem Fall, wenn die Koordinaten des Zielgebietes unbekannt sind? Wie in den vorangegangenen Beispielen gezeigt wurde, werden diese aber zur Erstellung der Karte benötigt.
Für diese Aufgabe steht der Geocoder zur Verfügung. Auch dieser ist ein JavaScript-Objekt, das erstellt und mit der Anfrage "gefüttert" werden muß. Nachdem dieses Geocoder-Objekt beim Google-Server nachgefragt hat, wird wiederum eine Callback-Funktion aufgerufen:
Delphi-Quellcode:
procedure TForm1.OnAPILoaded;
var
GeocoderRequest: TGeocoderRequest;
begin
with Script do
begin
GeocoderRequest:=TGeocoderRequest.Create; //GeocoderRequest-Objekt anlegen
GeocoderRequest.Address:='Mount Kilimanjaro'; //zu kodierende Adresse
Google.Maps.Geocoder.Geocode(GeocoderRequest,GeocoderCallback); //Geocoder-Objekt erstellen und Kodierung vom Server anfordern
end;
end;
procedure TForm1.GeocoderCallback(Sender: TObject; Results: TGeocoderResults; Status: String);
var
LatLng: TLatLng;
//...
begin
with Script do
begin
if Status=Google.Maps.GeocoderStatus.Ok then //Kodierungsanfrage wurde ordnungsgemäß bearbeitet
begin
LatLng:=Results[0].Geometry.Location; //erste Adresse aus der Kodierungsanfrage
//Karte neu anlegen bzw. neu zentrieren...
end else ShowMessage(Status);
end;
Praktisch wäre es jetzt noch, auch die Höhe des gewünschten Punktes auf der Landkarte zu ermitteln. Dafür ist der Elevation-Service der richtige Ansprechpartner. Genau wie der Geocoder besteht er aus einem JavaScript-Objekt, das die Anfrage an Google weiterleitet und nach dem Empfang die Antwort an eine entsprechende Callback-Funktion übergibt. In Delphi sieht das so aus:
Delphi-Quellcode:
procedure TForm1.GeocoderCallback(Sender: TObject; Results: TGeocoderResults; Status: String);
var
//...
ElevationRequest: TLocationElevationRequest;
begin
with Script do
begin
//...
ElevationRequest:=TLocationElevationRequest.Create; //ElevationRequest-Objekt anlegen
ElevationRequest.Locations.Add(LatLng); //Ort für die Abfrage der Höhe
if ElevationServices.Count=0 //noch kein ElevationService-Objekt vorhanden
then Google.Maps.ElevationService; //-> neu anlegen
ElevationServices[0].GetElevationForLocations(ElevationRequest,ElevationCallback);
//...
end;
end;
procedure TForm1.ElevationCallback(Sender: TObject; Results: TElevationResults; Status: String);
begin
with Script do
begin
if Status=Google.Maps.ElevationStatus.Ok
then //irgendetwas mit den Daten machen
else ShowMessage(Status);
end;
end;
In der Demo wird mit Hilfe der ermittelten Daten ein anklickbarer Marker erstellt.
Als kleiner Zusatz wird demonstriert, wie ein Screenshot vom WebBrowser gemacht werden kann.
Demo_5.zip enthält die Komponente TImage32 aus dem Paket Graphics32, Demo_5_ohne_TImage32.zip arbeitet nur mit TImage und ist deshalb auch ohne Graphics32 compilierbar.
Compilierte Exe und Quelltext (ohne Exe):