Google Maps dispose déjà en natif d'un layer Panoramio nous allons voir comment porter cette fonctionnalité vers toutes les apis disponible dans notre composant Delphi TECMap.
Nous allons créer une classe sur le même modèle que celle qui gère la création interactive d'une route c'est pourquoi nous ne détaillerons pas le code commun.
Fonctionnement
Le principe est simple, chaque fois que la vue de la carte change nous récupérons les images panoramio disponible dans la zone visible, avant de les afficher on les place dans un groupe pour pouvoir les manipuler plus facilement.
On se branche sur l'évènement OnChangeMapBounds pour détecter le changement de vue.
Pour la recherche d'images on utilise PanoramioView.Search, elle est lancée dans un Thread séparé, nous devons nous brancher sur l'évènement OnPanoramioSearch pour récupèrer notre liste d'images.
On va transformer chaque image en marker et gérer le Click pour pouvoir afficher une InfoWindow contenant le titre et l'image en taille moyenne.
Utilisation de la classe TPanoramioLayer
FPanoramioLayer :=
TPanoramioLayer.create;
...
// connect TECMap component for
show Panoramio layer
FPanoramioLayer.Map := map;
// deconnect layer
FPanoramioLayer.Map := nil
Source de TPanoramioLayer
unit
UPanoramioLayer;
interface
uses Windows, SysUtils,
Classes, Graphics, ECMaps, UECMapUtil;
type
TOnPanoramioLayerPhotoClick = procedure(sender: Tobject; const PhotoId : integer) of object;
TPanoramioLayer = class
private
FECMap : TECMap;
FOldOnPanoramioSearch : TOnPanoramioSearch;
FOldOnChangeMapBounds : TNotifyEvent;
FOnPanoramio : TNotifyEvent;
FOnClick : TOnPanoramioLayerPhotoClick;
FChangedBounds,
FInfowindow,
FShow : boolean;
FIdInfoWindow,
FMaxPhoto : integer;
procedure
setMap(const
ecMap:TECMap);
procedure
setShow(const
value:boolean);
procedure
AssignEvents;
procedure
RestoreEvents;
procedure
doOnPanoramioSearch(sender: TObject; const First,Last: Integer);
procedure
doOnChangeMapbounds(sender: TObject);
procedure
doOnMarkerClick(sender: Tobject; const Index: integer;
const dLatitude, dLongitude:
double);
public
constructor Create ;
destructor Destroy ;
override;
procedure Clear;
property Map : TECMap
read FECMap write setMap;
property MaxPhoto : integer
read FMaxPhoto write FMaxPhoto;
property Show : boolean
read FShow write setShow;
property Infowindow :
boolean read FInfowindow
write FInfowindow;
property OnPanoramio :
TNotifyEvent read
FOnPanoramio write
FOnPanoramio;
property OnClick :
TOnPanoramioLayerPhotoClick read FOnClick write FOnClick;
end;
implementation
constructor
TPanoramioLayer.Create;
begin
FMaxPhoto := 300;
FInfowindow := true;
inherited;
end;
destructor
TPanoramioLayer.Destroy ;
begin
Clear;
Map := nil;
inherited;
end;
procedure
TPanoramioLayer.AssignEvents;
begin
if not assigned(Map) then exit;
// save the events of
Origins
FOldOnPanoramioSearch := Map.OnPanoramioSearch;
FOldOnChangeMapBounds := Map.OnChangeMapBounds;
// connect to the events that
interest us
Map.OnPanoramioSearch := doOnPanoramioSearch;
Map.OnChangeMapBounds := doOnChangeMapbounds;
end;
// Reassign the events of
origins
procedure
TPanoramioLayer.RestoreEvents;
begin
if not assigned(Map) then exit;
Map.InfoWindows.delete(FIdInfoWindow);
end;
procedure
TPanoramioLayer.setMap(const
ecMap:TECMap);
begin
Clear;
RestoreEvents;
FECMap := ecMap;
FIdInfoWindow := -1;
FChangedBounds := false;
AssignEvents;
if assigned(FECMap)
then Show := true;
end;
procedure
TPanoramioLayer.Clear;
begin
if not assigned(Map) then exit;
Map.Groups['panoramio'].Delete;
end;
procedure
TPanoramioLayer.setShow (const value:boolean);
begin
// delete old images
Clear;
if value then
begin
Map.PanoramioView.LatSW := Map.SouthWestLatitude;
Map.PanoramioView.LatNE := Map.NorthEastLatitude;
Map.PanoramioView.LngSW := Map.SouthWestLongitude;
Map.PanoramioView.LngNE := Map.NorthEastLongitude;
// search for images, called
doOnPanoramioSearch when they are found
Map.PanoramioView.Search;
end;
FShow := value;
end;
// triggered by Show :=
true
procedure
TPanoramioLayer.doOnPanoramioSearch(sender: TObject;
const First,Last:
Integer);
var i,j:integer;
marker : TECMapMarker;
Lat,Lng : double;
url : string;
begin
for i := first to Last -
1 do
begin
Lat := Map.PanoramioView.photo_lat[i];
Lng := Map.PanoramioView.photo_lng[i];
url :=
remplace_str(Map.PanoramioView.photo_file_url[i],
'/medium/', '/mini_square/');
j := Map.AddMarker(lat,lng);
marker := Map.Markers[j];
marker.Draggable := false;
marker.Icon := url;
marker.Group := Map.Groups['panoramio'];
marker.Tag := i;
marker.OnMarkerClick := doOnMarkerClick;
end;
Map.Groups['panoramio'].show;
if assigned(FOnPanoramio)
then
FOnPanoramio(self);
if
(Map.PanoramioView.HasMore) and (Map.Groups['panoramio'].count<MaxPhoto)
then
begin
Map.PanoramioView.NextSearch;
exit;
end;
if
assigned(FOldOnChangeMapBounds) and FChangedBounds then
FOldOnChangeMapBounds(self);
FChangedBounds := false;
end;
procedure
TPanoramioLayer.doOnChangeMapbounds(sender:
TObject);
begin
if FChangedBounds
then exit;
FChangedBounds := true;
Show := true;
end;
procedure
TPanoramioLayer.doOnMarkerClick(sender: Tobject;
const Index: integer;
const dLatitude, dLongitude:
double);
var i:integer;
s : string;
begin
if not assigned(Map.Markers[index]) then exit;
if Infowindow then
begin
i := Map.Markers[index].tag;
s := '<h3>'+Map.PanoramioView.photo_title[i]+
'</h3>'+
Map.PanoramioView.HtmlPhoto(i,pimMedium)+
Map.PanoramioView.HtmlCopyright(i) ;
if FIdInfoWindow<
0 then
FIdInfoWindow := Map.InfoWindows.add(s)
else
Map.InfoWindows[FidInfoWindow].Content := s;
// for Bing maps
Map.InfoWindows[FidInfoWindow].SetOptions('width :550, height
:450,zIndex:500');
Map.InfoWindows[FidInfoWindow].SetPosition(dLatitude,
dLongitude);
Map.InfoWindows[FidInfoWindow].Open := true;
end;
if assigned(FOnClick)
then
FOnClick(self,Map.Markers[index].tag);
end;
end.