Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Google Maps API mit lokalen Bildern? (https://www.delphipraxis.net/168435-google-maps-api-mit-lokalen-bildern.html)

AndyK 21. Mai 2012 17:08

Google Maps API mit lokalen Bildern?
 
Hallo,

ich nutze die Google Maps API (3.0) in meiner D5 Anwendung. Dabei verwende ich zwei eigene PNG Bilder als Marker. Derzeit liegen diese auf einem Server.
Ist es möglich diese lokal im Programmverzeichnis oder als Ressource zu speichern und zu nutzen?

Gruss
Andy

Thom 21. Mai 2012 17:55

AW: Google Maps API mit lokalen Bildern?
 
Hallo Andy,

ja, da gibt es viele Möglichkeiten.
Zu Beginn ist allerdings die Frage zu klären, wie Du das API ansprichst - also über eine Komponente (falls ja, welche) oder über die Exec-Methode des Browsers. Dann wäre auch noch wichtig zu wissen, welchen Browser Du zur Anzeige verwendest: Den Internet Explorer (TWebBrowser, TEmbeddedWB) oder Chromium Embedded?

AndyK 21. Mai 2012 20:40

AW: Google Maps API mit lokalen Bildern?
 
Hallo Thom,

ich arbeite mit der TWebBrowser Komponente. Über eine Konstante lade ich das Java-Script für die Maps. Bei "function PutMarkerBlue" und "function PutMarker" werden die Marker als Image definiert. Den Großteil dieser Einbindung hatte ich aus einem Tutorial, könnte also dem Ein oder Anderen bekannt vorkommen ;) :

Delphi-Quellcode:
const
HTMLStr: AnsiString =
'<html> '+
'<head> '+
'<meta name="viewport" content="initial-scale=1.0, user-scalable=yes" /> '+
'<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script> '+
'<script type="text/javascript"> '+
''+
''+
' var geocoder; '+
' var map; '+
' var trafficLayer;'+
' var bikeLayer;'+
' var markersArray = [];'+
''+
''+
' function initialize() { '+
'   geocoder = new google.maps.Geocoder();'+
'   var latlng = new google.maps.LatLng(49.067231,10.837039); '+
'   var myOptions = { '+
'     zoom: 12, '+
'     center: latlng, '+
'     mapTypeId: google.maps.MapTypeId.HYBRID'+
'   }; '+
'   map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); '+
'   trafficLayer = new google.maps.TrafficLayer();'+
'   bikeLayer = new google.maps.BicyclingLayer();'+
'   map.set("streetViewControl", false);'+
' } '+
''+
''+
' function codeAddress(address) { '+
'   if (geocoder) {'+
'     geocoder.geocode( { address: address}, function(results, status) { '+
'       if (status == google.maps.GeocoderStatus.OK) {'+
'         map.setCenter(results[0].geometry.location);'+
'         PutMarker(results[0].geometry.location.lat(), results[0].geometry.location.lng(), results[0].geometry.location.lat()+","+results[0].geometry.location.lng());'+
'       } else {'+
'         alert("Geocode was not successful for the following reason: " + status);'+
'       }'+
'     });'+
'   }'+
' }'+
''+
''+
' function codeAddressBlue(address) { '+
'   if (geocoder) {'+
'     geocoder.geocode( { address: address}, function(results, status) { '+
'       if (status == google.maps.GeocoderStatus.OK) {'+
'         map.setCenter(results[0].geometry.location);'+
'         PutMarkerBlue(results[0].geometry.location.lat(), results[0].geometry.location.lng(), results[0].geometry.location.lat()+","+results[0].geometry.location.lng());'+
'       } else {'+
'         alert("Geocode was not successful for the following reason: " + status);'+
'       }'+
'     });'+
'   }'+
' }'+
''+
''+
' function GotoLatLng(Lat, Lang) { '+
'  var latlng = new google.maps.LatLng(Lat,Lang);'+
'  map.setCenter(latlng);'+
'  PutMarker(Lat, Lang, Lat+","+Lang);'+
' }'+
''+
''+
'function ClearMarkers() {  '+
' if (markersArray) {        '+
'   for (i in markersArray) {  '+
'     markersArray[i].setMap(null); '+
'   } '+
' } '+
'}  '+
''+
' function PutMarkerBlue(Lat, Lang, Msg) { '+
'  var latlng = new google.maps.LatLng(Lat,Lang);'+
'  var image = "http://www.domain.de/images/blue-pushpin.png";'+    //
'  var marker = new google.maps.Marker({'+
'     position: latlng, '+
'     map: map,'+
'     icon: image,'+ //
'     title: "Alarmierte Wehr"'+
' });'+
' markersArray.push(marker); '+
' }'+
''+
' function PutMarker(Lat, Lang, Msg) { '+
'  var latlng = new google.maps.LatLng(Lat,Lang);'+
'  var image = "http://www.domain.de/images/firedept.png";'+    //
'  var marker = new google.maps.Marker({'+
'     position: latlng, '+
'     map: map,'+
'     icon: image,'+ //
'     title: "Einsatzort"'+
' });'+
' markersArray.push(marker); '+
' }'+
''+
''+
' function TrafficOn()  { trafficLayer.setMap(map); }'+
''+
' function TrafficOff() { trafficLayer.setMap(null); }'+
''+''+
' function BicyclingOn() { bikeLayer.setMap(map); }'+
''+
' function BicyclingOff(){ bikeLayer.setMap(null);}'+
''+
' function StreetViewOn() { map.set("streetViewControl", true); }'+
''+
' function StreetViewOff() { map.set("streetViewControl", false); }'+
''+
''+'</script> '+
'</head> '+
'<body onload="initialize()"> '+
' <div id="map_canvas" style="width:100%; height:100%"></div> '+
'</body> '+
'</html> ';
FormCreate läd dann entsprechend die ersten Daten. Über einen Startparameter wird ein Ortsname übertragen und dann in der Karte gesucht:

Delphi-Quellcode:
procedure TfrmMain.FormCreate(Sender: TObject);
var
   aStream    : TMemoryStream;
   adr   : string;
begin
   WebBrowser1.Navigate('about:blank');
    if Assigned(WebBrowser1.Document) then
    begin
      aStream := TMemoryStream.Create;
      try
         aStream.WriteBuffer(Pointer(HTMLStr)^, Length(HTMLStr));
         //aStream.Write(HTMLStr[1], Length(HTMLStr));
         aStream.Seek(0, soFromBeginning);
         (WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(aStream));
      finally
         aStream.Free;
      end;
      HTMLWindow2 := (WebBrowser1.Document as IHTMLDocument2).parentWindow;

    end;

    adresse := ParamStr(1);


    if adresse <> '' then
    begin
       Edit1.Text := adresse;
       adr := adresse;
       adr := StringReplace(StringReplace(Trim(adr), #13, ' ', [rfReplaceAll]), #10, ' ', [rfReplaceAll]);
       HTMLWindow2.execScript(Format('codeAddress(%s)',[QuotedStr(adr)]), 'JavaScript');
    end;

end;
Über welchen Weg kann ich nun die zwei Bilder lokal speichern oder in die Anwendung einbinden um sie in der Karte zu nutzen? Ich hatte es schon als Ressource eingebunden, jedoch blieb ich beim Einbinden hängen.

Gruß
Andy

Thom 21. Mai 2012 21:23

AW: Google Maps API mit lokalen Bildern?
 
Hallo Andy,

im Quelltext sehe ich
Code:
  var image = "http://www.domain.de/images/blue-pushpin.png";
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    icon: image,
    title: "BlaBla"});
Da der IE lokale Dateien akzeptiert, könntest Du bei "image" auch den Ort des Bildes auf der Festplatte angeben. Das wäre der einfachste, aber leider auch unflexibelste Weg.
Viel besser wäre die Übergabe als Base64-codiertes Bild an die Methode "setIcon" des Markers. Damit ist es möglich, das Bild aus einer beliebigen Quelle zu entnehmen - beispielsweise TImageList, TImage oder auch dynamisch erzeugt.

Aber bevor ich das jetzt ausführlich erkläre, mal noch eine prinzipielle Frage: Willst Du unbedingt mit HTML und JavaScript arbeiten oder wäre auch eine reine Delphi-Lösung annehmbar?
Also zum Beispiel so etwas:
Delphi-Quellcode:
  Markers[0].SetIcon(Encode64(Image1));
  Markers[1].SetIcon(Encode64(Image2));

AndyK 21. Mai 2012 21:38

AW: Google Maps API mit lokalen Bildern?
 
Zitat:

Zitat von Thom (Beitrag 1167512)
Aber bevor ich das jetzt ausführlich erkläre, mal noch eine prinzipielle Frage: Willst Du unbedingt mit HTML und JavaScript arbeiten oder wäre auch eine reine Delphi-Lösung annehmbar?
Also zum Beispiel so etwas:
Delphi-Quellcode:
  Markers[0].SetIcon(Encode64(Image1));
  Markers[1].SetIcon(Encode64(Image2));

Über welchen Weg ich dabei gehe ist mir ziemlich egal ;) Hauptsache es funktioniert zuverlässig. Dann werde ich mir das die Tage mal vornehmen. Vielen Dank schonmal für deine Hilfe!

Thom 21. Mai 2012 21:55

AW: Google Maps API mit lokalen Bildern?
 
Hallo Andy,

also wenn es Dir egal ist, dann schau Dir vielleicht mal das Google Maps Framework hier im Forum an. Damit kannst Du ausschließlich mit Delphi alle API-Funktionen nutzen. Dafür hätte ich dann auch eine Demo zur Nutzung von lokalen Icons bei Markern.

Thom 22. Mai 2012 12:26

AW: Google Maps API mit lokalen Bildern?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe mal schnell das HTML/JavaScript-Beispiel von Dir mit Hilfe des Frameworks (Version 3 mit Interfaces) umgesetzt.

Anhang 36943

Die Erstellung der Karte erfolgt in zwei Schritten. Diese Trennung ist zwar keine Pflicht - sie ist aber sinnvoll, um nach einem Refresh (Taste F5) nur den Code auszuführen, der für die Darstellung notwendig ist:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    [...]
  private
    FBikerLayer: IBicyclingLayer;
    FGeocoder: IGeocoder;
    FMap: IMap;
    FTrafficLayer: ITrafficLayer;
    [...]
  public
    property BikerLayer: IBicyclingLayer read FBikerLayer write FBikerLayer;
    property Geocoder: IGeocoder read FGeocoder write FGeocoder;
    property Map: IMap read FMap write FMap;
    property TrafficLayer: ITrafficLayer read FTrafficLayer write FTrafficLayer;
  end;

procedure TForm1.FormShow(Sender: TObject);
begin
  with Script(WebBrowser1) do
    if not APILoaded
      then LoadAPIAsync(InitMap);
end;

procedure TForm1.InitMap(Sender: IObject);
var
  MapOptions: IMapOptions;
begin
  with Sender as IScript do
  begin
    MapOptions:=New(Google.Maps.MapOptions);
    with MapOptions do
    begin
      Zoom:=12;
      Center:=New(Google.Maps.LatLng(49.067231,10.837039));
      MapTypeID:=Google.Maps.MapTypeID.Hybrid;
      StreetViewControl:=false;
    end;
    Map:=New(Google.Maps.Map(MapOptions));
    Geocoder:=New(Google.Maps.Geocoder);
    TrafficLayer:=New(Google.Maps.TrafficLayer);
    BikerLayer:=New(Google.Maps.BicyclingLayer);
    TrafficLayerVisible.Checked:=false;
    BikerLayerVisible.Checked:=false;
    StreetViewControlVisible.Checked:=false;
  end;
end;
Dabei wird das API geladen, die Karte entsprechend der Einstellungen angelegt sowie die zusätzlichen Layer und der Geocoder erstellt. Der Rest besteht aus der Initialisierung der Steuerelemente, über die die Ein- und Ausblendung der Layer erfolgt:
Delphi-Quellcode:
procedure TForm1.TrafficLayerVisibleClick(Sender: TObject);
begin
  if assigned(TrafficLayer) then
    if TrafficLayerVisible.Checked
      then TrafficLayer.SetMap(Map)
      else TrafficLayer.SetMap(nil);
end;

procedure TForm1.BikerLayerVisibleClick(Sender: TObject);
begin
  if assigned(BikerLayer) then
    if BikerLayerVisible.Checked
      then BikerLayer.SetMap(Map)
      else BikerLayer.SetMap(nil);
end;

procedure TForm1.StreetViewControlVisibleClick(Sender: TObject);
begin
  if assigned(Map)
    then Map.&Set('streetViewControl',StreetViewControlVisible.Checked); //für ältere Compiler "Set_"
end;

procedure TForm1.ClearMarkersClick(Sender: TObject);
begin
  if Script<>nil
    then Script.Markers.Clear;
end;
Um eine Adresse zu kodieren, wird einfach eine asynchrone Geocoding-Anfrage gestartet:
Delphi-Quellcode:
procedure TForm1.GotoAddressClick(Sender: TObject);
var
  Request: IGeocoderRequest;
begin
  if assigned(Geocoder) then
  begin
    Request:=New(Script.Google.Maps.GeocoderRequest);
    Request.Address:=Address.Text;
    Geocoder.Geocode(Request,GeocoderCallback);
  end;
end;
Ist die Antwort für die Geocoding-Anfrage eingetroffen, wird die GeocoderCallback-Methode aufgerufen. Dabei kann es sich um eine anonyme Methode handeln (ab Delphi 2009) oder um eine Objekt-Methode:
Delphi-Quellcode:
procedure TForm1.GeocoderCallback(Sender: IObject; Result: IGeocoderResultArray; const Status: String);
var
  MarkerOptions: IMarkerOptions;
begin
  with Script do
  begin
    if Status=Google.Maps.GeocoderStatus.OK then
    begin
      Map.PanTo(Result[0].Geometry.Location);
      MarkerOptions:=New(Google.Maps.MarkerOptions);
      with MarkerOptions do
      begin
        Position:=Result[0].Geometry.Location;
        Map:=Self.Map;
        Icon:=Encode64(Image1);
        Title:='Image1';
      end;
      New(Google.Maps.Marker(MarkerOptions));
    end else Showmessage('Geocode was not successful for the following reason: '+Status);
  end;
end;
Hier wird's jetzt interessant, da in dieser Methode ein Marker erstellt wird, dessen Icon einfach aus einer TImage-Komponente entnommen wird. Die Funktion Encode64 macht es möglich.
Viel einfacher - glaube ich - geht es nicht.

AndyK 22. Mai 2012 17:10

AW: Google Maps API mit lokalen Bildern?
 
Oh Wow, in das Framework muss ich mich erstmal reinarbeiten ;) Wie schaffe ich es, dass ich die Funktion Encode64 nutzen kann? ;) Damit hat mein armes Delphi 5 irgendwie ein Problem :roll:

Thom 22. Mai 2012 21:21

AW: Google Maps API mit lokalen Bildern?
 
Die Funktionen zur Base64-Kodierung befinden sich in der Version 2.x des Frameworks etwas verstreut in den beiden Units BrowserTools.pas und Base64.pas im Verzeichnis GoogleMaps\Source\JScript. Encode64 akzeptiert auch nur Bitmaps sowie PNG- und GIF-Bilder. Das ändert sich in Version 3: Dort sind alle Base64-Funktionen in der Unit Tools.Base64.pas zusammengefaßt und können auch TPicture- und TImage-Parameter verarbeiten. Trotz der Punkte im Dateinamen sind die Units zu Delphi 5 kompatibel.
Momentan wäre es möglich, ein Bild aus einer TImage-Komponente so zu verarbeiten:
Delphi-Quellcode:
  Icon:=Encode64(Image1.Picture.Graphic as TPNGImage); //bzw.
  Icon:=Encode64(Image1.Picture.Graphic as TPNGObject);
Da in Delphi 5 noch kein PNG-Support enthalten ist, muß die PNG-Unit von Gustavo Daud installiert und deren Verwendung in der Datei GoogleMaps\gmConfig.inc aktiviert werden.

AndyK 23. Mai 2012 08:56

AW: Google Maps API mit lokalen Bildern?
 
Ich steh mit diesem Framework auf einem gewaltigen Schlauch :( Zig Fehlermeldungen - ist die eine behoben erscheint die nächste. Die Demos laufen aber problemlos. Nachdem mein Programm mit Java-Script perfekt läuft und es nur die Bilder der Marker sind die auf einem Server liegen, lass ich es einfach so ;) Dennoch danke ich für deine Hilfsbereitschaft sehr herzlich! :)

Vieleicht gehe ich die Sache in meinem Juni-Urlaub an ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:22 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz