Composant Delphi / Google Maps / OpenStreetMap / Leaflet  / Mappilary / Native Maps 100% Delphi 0% WebBrowser 0% Javascript

TECNativeMap

TECNativeMap vous permet d'utiliser les cartes d'OpenStreetMap, de MapQuest, ArcGIS World, d'OpenCycleMap, de Google, de MapBox, d'OPNV, de TomTom, de PTV Group et d'autres encore mais aussi vos propres serveurs, et de gérer vos propres composants à y intégrer.

Pour sélectionner un fournisseur de cartes utilisez la propriété TileServer

map.TileServer := tsOsm;

Google

Pour utiliser les tuiles de Google vous devez entrer votre clef d'API dans GoogleKey, allez sur la plateforme de Google pour la générer.

map.Google.ApiKey := 'your api key';
map.TileServer := tsGoogle;

// 3 map types to choose from
map.TileServerInfo.MapStyle := 'satellite';
map.TileServerInfo.MapStyle := 'terrain';
map.TileServerInfo.MapStyle := 'roadmap';

// set language, default en-US
map.Google.Lang := 'fr-FR';
// set region, default US
map.Google.Region := 'FR';
// traffic is also supported
map.TrafficLayer := true;
// styles also
map.Google.Styles := '[{"featureType": "all","stylers": [{ "color": "#C0C0C0" }]'+
'},{"featureType": "road.arterial", "elementType": "geometry",'+
'"stylers": [ { "color": "#CCFFFF" } ]},{'+
'"featureType": "landscape","elementType": "labels", "stylers": [{ "visibility": "off" }'+
']}]';

Fig. 1 roadmap

Fig. 2 terrain

Fig. 3 satellite

Fig. 4 Demo Google Map

Bing

En renseignant la propriété BingKey avec votre clef Bing vous pourrez utiliser les tuiles de Bing Maps ( tsBingRoad, tsBingAerial, tsBingAerialLabels )

map.BingKey := YOUR_BING_KEY
map.TileServer := tsBingRoad;

Fig. 5 Bing Maps

Here

En renseignant la propriété HereApiKey vous pouvez utiliser les tuiles de Here


map.TileServer := tsHere;
map.HereApiKey := := 'your_api_key' ;
// select style
map.TileServerInfo.MapStyle := 'explore.day';
map.TileServerInfo.MapStyle := 'lite.day';
map.TileServerInfo.MapStyle := 'explore.night';
map.TileServerInfo.MapStyle := 'satellite.day';
map.TileServerInfo.MapStyle := 'explore.satellite.day';

Fig. 6 Here style explore.day

MapBox

Pour utiliser les tuiles de MapBox ( tsMapBoxSatellite, tsMapBoxStreets,tsMapBoxStreetsSatellite,tsMapBoxStreetsBasic ) il vous suffit d'entrer votre token dans MapBoxToken.

Vous devez aussi indiquer une taille de tuile de 512

1
// use your token
map.MapBoxToken := 'pk.xxx';

// The mapbox raster tiles are now 512 x 512 so you need to specify a tile size of 512

map.TileSize := 512;
map.TileServer := tsMapBoxStreets;

// To access all available raster tile styles use the tsMapBoxStreetsBasic server and specify a style

map.TileSize := 512;
map.TileServer := tsMapBoxStreetsBasic;
map.TileServerInfo.MapStyle := 'navigation-day-v1';
map.TileServerInfo.MapStyle := 'navigation-night-v1';
map.TileServerInfo.MapStyle := 'light-v10';
map.TileServerInfo.MapStyle := 'dark-v10';

Fig. 7 MapBoxStreets

TomTom

Pour utiliser les tuiles de TomTom ( tsTomTomBasic, tsTomTomHybrid, tsTomTomNight, tsTomTomIncident, tsTomTomFlow ) vous devez obtenir une clef et renseigner la propriété TomTomKey de votre carte.

map.TomTomKey := your_tomtom_key
map.TileServer := tsTomTomBasic;

Fig. 8 TomTom Basic


map.TileServer := tsHereSatellite;

// add overlay tiles for TomTom Hybrid
map.AddOverlayTileServer(tsTomTomHybrid);

// mandatory, reset api key for overlay
map.TomTomKey := Your_TomTomKey;

Fig. 9 Here Satellite + TomTom Hybrid

Pour tsTomTomIncident et tsTomTomFlow vous avez le choix entre 4 styles


var oc:TECOverlayTileLayer;
...
// add overlay tiles for incident
oc := map.AddOverlayTileServer(tsTomTomIncident);

oc.MapStyle := 's1'; // default style
oc.MapStyle := 's2';
oc.MapStyle := 's3';
oc.MapStyle := 'night';

// mandatory, reset api key for overlay
// use your key !
map.TomTomKey := map.TomTomKey;

oc := map.AddOverlayTileServer(tsTomTomflow);

oc.MapStyle := 'absolute'; // default style
oc.MapStyle := 'relative';
oc.MapStyle := 'relative-delay';
oc.MapStyle := 'reduced-sensitivity';

// mandatory, reset api key for overlay
// use your key !
map.TomTomKey := map.TomTomKey;

PTV Group

Vous devez obtenir votre clef d'api pour pouvoir utiliser ces cartes.

Vous pouvez utiliser les tuiles de PTV comme carte de base ou alors en superposition par dessus n'importe quel fond de cartes.

Fig. 10 PTV demo

property ApiKey: string

Votre clef d'api

property BaseMapLayer: TPTVBaseMapLayer

Le type de la carte de base au choix (none, amber, blackmarble, classic, gravelpit, sandbox,silica, silkysand, satellite)

none permet de rebasculer sur un fond de carte autre que PTV et géré par TileServer

1

property ForegroundLayers: TPTVForegroundLayers

Vous pouvez associer plusieurs layers sur votre fond de carte PTV, au choix [background, transport, labels, trafficIncidents,trafficPatterns, restrictions, toll]

Si vous n'incluez pas background la carte de base ne sera pas affichée

2

Si vous utilisez le fond de carte satellite vous devez utiliser OverlayLayers pour incruster des layers PTV

2

property OverlayLayers: TPTVForegroundLayers

Utilisez cette propriétée pour incruster un ou plusiers layers PTV sur un fond de carte non PTV, au choix [transport, labels, trafficIncidents,trafficPatterns, restrictions, toll]

property PTV_COPYRIGHT: string

Le copyright affiché avec la carte de base PTV

property VehicleType: TPTVvehicleType

Permet de choisir des cartes spécifiques pour car ou truck
procedure TPTVForm.FormCreate(Sender: TObject);
begin
// see https://developer.myptv.com/en/documentation
Map.PTV.ApiKey := 'your api key';
end;
// select PTV base map
procedure TPTVForm.basemaplayerChange(Sender: TObject);
begin
case basemaplayer.ItemIndex of
0: Map.PTV.basemaplayer := TPTVBaseMapLayer.sandbox;
1: Map.PTV.basemaplayer := TPTVBaseMapLayer.classic;
2: Map.PTV.basemaplayer := TPTVBaseMapLayer.silkysand;
3: Map.PTV.basemaplayer := TPTVBaseMapLayer.amber;
4: Map.PTV.basemaplayer := TPTVBaseMapLayer.blackmarble;
5: Map.PTV.basemaplayer := TPTVBaseMapLayer.gravelpit;
6: Map.PTV.basemaplayer := TPTVBaseMapLayer.silica;
7: Map.PTV.basemaplayer := TPTVBaseMapLayer.satellite;
// cancel PTV base map
8: Map.PTV.basemaplayer := TPTVBaseMapLayer.none;
end;
end;

// add PTV layers on PTV base map
procedure TPTVForm.LabelsClick(Sender: TObject);
var
fl: TPTVForegroundLayers;
begin
fl := [];

if Labels.Checked then
fl := fl + [TPTVForegroundLayer.Labels];

if Background.Checked then
fl := fl + [TPTVForegroundLayer.Background];

if Transport.Checked then
fl := fl + [TPTVForegroundLayer.Transport];

if Trafficincidents.Checked then
fl := fl + [TPTVForegroundLayer.Trafficincidents];

if TrafficPatterns.Checked then
fl := fl + [TPTVForegroundLayer.TrafficPatterns];

if Restrictions.Checked then
fl := fl + [TPTVForegroundLayer.Restrictions];

if Toll.Checked then
fl := fl + [TPTVForegroundLayer.Toll];

Map.PTV.ForegroundLayers := fl;

end;

// add PTV layer on a non-PTV map base
procedure TPTVForm.OLabelsClick(Sender: TObject);
var
fl: TPTVForegroundLayers;
begin
fl := [];

if OLabels.Checked then
fl := fl + [TPTVForegroundLayer.Labels];

if OTransport.Checked then
fl := fl + [TPTVForegroundLayer.Transport];

if OTrafficIncidents.Checked then
fl := fl + [TPTVForegroundLayer.Trafficincidents];

if OTrafficPatterns.Checked then
fl := fl + [TPTVForegroundLayer.TrafficPatterns];

if ORestrictions.Checked then
fl := fl + [TPTVForegroundLayer.Restrictions];

if OToll.Checked then
fl := fl + [TPTVForegroundLayer.Toll];

Map.PTV.OverlayLayers := fl;
end;

Vous pouvez afficher votre fond de carte en niveau de gris avec map.Grayscale := true

1

Liste des serveurs prédéfinis

tsOpenMapQuest, tsOpenMapQuestSat, tsCloudMade, tsOSM, tsOpenCycleMap, tsOPNV, tsArcGisWorldTopoMap, tsArcGisWorldStreetMap, tsArcGisWorldImagery, tsBingRoad, tsBingAerial, tsBingAerialLabels, tsOwnerDraw, tsCustom, tsHere, tsMapBoxSatellite, tsMapBoxStreets,tsMapBoxStreetsSatellite, tsMapBoxStreetsBasic, tsMapBoxOutdoors, tsYandexNormal, tsYandexSatellite, tsYandexHybrid, tsYandexPeople, tsDigitalGlobeRecent, tsDigitalGlobeTerrain, tsOsmFr, tsOpenTopoMap, tsMapillary, tsTomTomBasic, tsTomTomHybrid, tsTomTomNight, tsTomTomIncident, tsTomTomFlow, tsHyddaFull, tsOsmDe, tsTopPlusWebOpen, tsTopPlusWebOpenGrey, tsbingCanvasGray, tsbingCanvasDark, tsbingCanvasLight, tsBaseOpenSnowMap, tsPisteOpenSnowMap, tsHotOsm, tsIgn, tsCyclOSM,tsTomTomSat,tsOpenRailWayMap,tsGoogle

Si vous essayez de télécharger des tuiles sur internet et qu'il n'y a pas de connexion, l'événément OnErrorConnexion de votre carte est déclenché.


OnlyLocal est alors mis à true pour éviter toute tentative de connexion, lorsque la connexion reviendra vous devrez remettre OnlyLocal à false, cela ne sera pas fait automatiquement.

1

Serveur de tuiles WMS

Vous pouvez utiliser un service WMS pour afficher vos tuiles.

// base map
map.TileServerWMS('https://ows.mundialis.de/services/service', 'TOPO-WMS');
// You can select a date in iso-8601 format
map.WMS_Time := '2023-10-19T09:00:00.000Z';
// show legend, Top Center, 85% opacity
map.WMS_Legend(true,lpTopCenter,85);

// overlay
var o : TECOverlayTileLayer;
o := map.AddOverlayTileServerWMS('https://ows.mundialis.de/services/service', 'OSM-Overlay-WMS');
// You can select a date in iso-8601 format
o.WMS_Time := '2023-10-19T09:00:00.000Z';
// show legend, Top Center, 85% opacity , Xmargin 4 , ymargin 4
o.WMS_Legend(true,lpTopCenter,85,4,4);

Utilisez votre propre serveur de tuiles

En plus des cartes précédente vous pouvez utiliser n'importe quel autre fournisseur utilisant le même format.

procedure TForm.FormCreate(Sender: TObject);
begin
Map.LocalCache := ExtractFilePath(application.exename) + 'cache';
Map.MaxZoom := 21;
// provider of custom tiles
Map.TileServerInfo.Name := 'OSM';
Map.TileServerInfo.GetTileFilename := GetOSMTile;
end;


procedure TForm.GetOSMTile(var TileFilename:string;const x,y,z:integer);
begin
TileFilename := 'https://tile.openstreetmap.org/' + inttostr(z) + '/' + inttostr(x) + '/' +
inttostr(y) + '.png' ;
end;


ColorFilter

Cette propriété vous permet de modifier/changer certaines couleurs de vos tuiles.

// shade of gray
map.ColorFilter.filter := fcGrey;
// color inversion
map.ColorFilter.filter := fcInvert;
// sepia color
map.ColorFilter.filter := fcSepia;
// use this non-filter to change only the light or dark setting
map.ColorFilter.filter := fcCustom;
// normal color
map.ColorFilter.filter := fcNone;
// Lightening and darkening are controlled by LightValue and DarkValue
// higher value is applied if filter <> fcNone and xValue>0

// change only the darkening
map.ColorFilter.filter := fcCustom;
map.ColorFilter.DarkValue := 64;
map.ColorFilter.LightValue := 0;

// invert color and change the Lightening
map.ColorFilter.filter := fcInvert;
map.ColorFilter.LightValue := 40;
map.ColorFilter.DarkValue := 0;

// You can also use the Dark and Light modes,
// which are shortcuts to Filter + LightValue.
map.Dark := true;
map.Light:= true;

Fig. 11 Filtre fcInvert

Uniquement sous Firemonkey, vous pourrez aussi définir certaines couleurs qui seront gardées ou que vous pourrez remplacer sans qu'elles ne soient modifiées par le filtre.

var c:TAlphaColor;
...
TAlphaColorRec(c).R := 247;
TAlphaColorRec(c).G := 250;
TAlphaColorRec(c).B := 191;
// 100% opacity
TAlphaColorRec(c).A := 255;

map.ColorFilter.Colors.Add(c);
map.ColorFilter.ActionColor := acKeep;
...
map.ColorFilter.Colors.Add(Old_color_1);
map.ColorFilter.Colors.Add(New_color_1);
map.ColorFilter.Colors.Add(Old_color_2);
map.ColorFilter.Colors.Add(New_color_2);
map.ColorFilter.Colors.ActionColor := acReplace;


// by default a tolerance of 1% is applied to the colors to keep or replace, you can pass to 10% in this way

map.ColorFilter.Tolerance := 0.1;

Fig. 12 Mode gris avec concervation d'une couleur

Fig. 13 Mode gris avec remplacement d'une couleur

Fig. 14 Mode dark avec remplacement d'une couleur

Inscrutation de tuiles

Vous pouvez utiliser autant de serveurs de tuiles que vous le voulez pour les afficher par dessus votre carte de base, l'exemple ci-dessous incruste une carte des nuages.

var overlay:TECOverlayTileLayer;
...
// overlay clouds tiles
overlay := map.AddOverlayTiles(GetWeatherTile);
// set name for directory
overlay.Name := 'OpenWeatherMap_Clouds';
// you can also use this syntax
overlay := map.AddOverlayTiles(GetWeatherTile,'OpenWeatherMap_Clouds');

// remove overlay
map.RemoveOverlayTiles(overlay);

...

procedure TForm.GetWeatherTile(var TileFilename:string;const x,y,z:integer);
begin
TileFilename := format('http://%s.tile.openweathermap.org/map/clouds/%d/%d/%d.png',[Char(Ord( 'a') + random(3)),z,x,y]);
end;


Fig. 15 Incrustation des nuages

Vous pouvez aussi utiliser un stream

procedure TForm.getOverlayTileStream(var TileStream: TMemoryStream;const x, y, z: integer);
begin
// here fill the stream with your tile

end;

...
map.AddOverlayStreamTiles(getOverlayTileStream);


Ou directement utiliser un serveur prédéfini transparent comme tsHereFlow ou tsHereTruckTransparent

// mix Bing Aerial Labels and Here Flow
map.TileServer := tsBingAerialLabels;
map.AddOverlayTileServer(tsHereFlow);


Autre exemple, utiliser les services d'OpenRailWayMap pour afficher les installations ferrovières.

var o : TECOverlayTileLayer;
// standard style
o := map.AddOverlayTileServer(tsOpenRailWayMap);
// other styles
o.MapStyle := 'maxspeed';
o.MapStyle := 'signals';
o.MapStyle := 'electrification';
o.MapStyle := 'gauge';

Fig. 16 OpenRailWayMap standard style

En mode VCL Votre overlay doit utiliser des pngs pour qu'il s'inscruste sur votre carte, sous FMX vous pouvez utiliser la propriété opacity.

3

var overlay:TECOverlayTileLayer;
...
// overlay clouds tiles
overlay := map.AddOverlayTiles(GetWeatherTile);

// set opacity 0..1
overlay.opacity := 0.5;


Utilisez RemoveAllOverlayTiles pour supprimer tous les overlays

Vous pouvez aussi incruster une image seule si elle est à l'échelle

2

Tuiles Vectorielles

A partir de la version 5.5 (octobre 2024) TECNativeMap offre un support minimaliste aux tuiles vectorielles telle que défini par MapBox

En l'état c'est un prototype non utilisable en production et qui ne recouvre que de façon très partielle les spécifications de style, le support 3D n'est pas envisagé à court ou moyen terme.

2

Fig. 17 Stadia.com osm bright

Fig. 18 Maptiler.com Basic

Connexion à un serveur de tuiles vectorielles

Tout ce que vous avez à faire c'est de passer l'url de votre style (au format json MapLibre), si nécessaire vous dverez y indiquer aussi votre clef d'api.

map.setVMTTileServer('https://tiles.stadiamaps.com/styles/osm_bright.json?api_key=YOUR_API_KEY');
map.setVMTTileServer('https://api.maptiler.com/maps/basic-v2/style.json?key=YOUR_API_KEY');

Vous pouvez aussi vous connecter manuellement comme cela

map.TileServer := tsCustom;
map.TileSize := 512;
map.MaxZoom := 14;
map.TileServerInfo.TileFormat := stVMT;
map.TileServerInfo.Name := 'NAME_OF_SERVER';
map.TileServerInfo.getTileFilename := GetVMTTile;
map.VectorStyles.JSON := 'json style';
// You can also load sprite definition files manually (url or local file),
// by default they are loaded using the files defined in the json style
map.VectorStyles.LoadFromFile(Url_SpritePng, Url_SpriteJSON);
...

procedure TForm1.GetVMTTile(var TileFilename:string;const x,y,z:integer);
begin
TileFilename := 'your_url_for_tileXYZ';
end;

Vous pouvez parcourir l'ensemble des styles, exemple ici on va remplir une listbox

procedure TForm1.buildListRules;
var i,j:integer;
List : TVectorLayerStyleRules ;
rule : TVectorLayerStyleRule;
begin
ListRules.Clear;
ListRules.BeginUpdate;
ListRules.OnChangeCheck := nil;

for i := 0 to map.VectorStyles.Layers.Count-1 do
begin
List := map.VectorStyles.VectorLayerStyles[ map.VectorStyles.Layers[i].name ] ;

if assigned(List) then
for j := 0 to List.count-1 do
begin
rule := List[j];

if assigned(rule) then
ListRules.ListItems[ListRules.Items.AddObject(rule.id,rule)].IsChecked := rule.Visible;
end;
end;

ListRules.OnChangeCheck := ListRulesChangeCheck;
ListRules.EndUpdate;

end;

Positionnement sur la carte

Vous pouvez déterminer les coordonnées du centre de la carte au travers des propriétés Latitude et Longitude, elles sont de type double et accessible en lecture/écriture

Vous pouvez directement modifier les coordonnées au travers de la procédure setCenter(const dlatitude,dlongitude:double)

PanTo(lat,lng) est équivalent mais un scroll sera effectué si le déplacement est minime autrement on va directement à la nouvelle position comme setCenter

Utilisez Move(direction,DistanceKM) pour effectuer un déplacement suivant une direction variant de 0 à 359° et sur une distance en KM

// Delphi map component ECNativeMap
var lat,lng:double;
begin
// get center of map
lat := map.Latitude;
lng := map.Longitude;
// move center of map
map.setCenter(lat+0.001,lng);
//
map.PanTo(lat+0.001,lng);

// move to south on 10.5km
map.Move(180,10.5);

end;

Position de la souris

Les latitude et longitude du point situé sous le curseur de la souris sont renvoyés par la propriété MouseLatLng

Vous pouvez vous brancher sur l'évènement OnMapMouseMove pour connaitre en temps réel votre position

Graticule

Affiche une grille indiquant les latitudes et longitudes.

Fig. 19 Graticule

map.Graticule.Visible := true;
map.Graticule.LineStyle := psDashDot; // psSolid, psDot, psDash
map.Graticule.LineColor := claBlack;
map.Graticule.LineSize := 1;
// default guDegrees;
// also guQTHLocator, guUTM and guLOC
map.Graticule.LabelUnit := guDecimalDegrees;
map.Graticule.LabelColor := claBlack;
map.Graticule.LabelFont.Style := [TFontStyle.fsBold];
map.Graticule.LabelPositions := [gpTop,gpRight,gpBottom,gpLeft];
// only firemonkey
map.Graticule.Opacity := 50; // 0..100

Réagir au changement de position

Lorsque le centre de la carte est déplacé, que cela soit par code ou directement à la souris, l'évènement OnMapMove(sender: Tobject;const dLatitude,dLongitude:double) est déclenché

Sender représente le composant ECMap qui a été modifié, dLatitude et dLongitude les nouvelles coordonnées, qui sont aussi accessible au travers de Latitude et Longitude

Lorsque la carte commence à bouger l'évènement OnMapDragStart est déclenché, puis OnMapDrag pendant le déplacement et OnMapDragEnd en fin de déplacement.

Vous pouvez aussi réagir lors du déplacement de la souris en vous branchant sur OnMapMouseMove

Zone affichée

Vous pouvez déterminer les coordonnées du point Nord Est (en haut à droite) et du point Sud Ouest (en bas à gauche) de la zone affichée par le composant au travers des propriétés NorthEastLatitude, NorthEastLongitude, SouthWestLatitude et SouthWestLongitude, elles sont de type double et accessible uniquement en lecture.

La procedure BoundingBox(maxLatitude,maxLongitude,minLatitude,minLatitude) limite la zone accessible de votre carte, l'événement OnOutOfBounds est déclenché si vous tentez d'accéder à une zone interdite.

Un appel à BoundinBox sans paramètre lève les limitations.

4

La procédure fitBounds(const dLatlo,dLnglo,dLathi,dLnghi:double) vous permet de d'ajuster la vue aux coordonnées passées.

Vous pouvez aussi lui passer un tableau contenant des groupes et ainsi obtenir une vue sur l'ensemble des éléments.

5
map.fitBounds([map['G1'],map['G2']]);

la procedure boundingCoordinates(const lat, lng, radius: double; var latSW, lngSW,latNE, lngNE: double); retourne les coordonnées d'une zone rectangulaire en fonction du point central et d'une distance en Km.

La fonction ContainsLatLng(var dLatitude,dLongitude:double):boolean vous indique si le point en dLatitude,dLongitude est dans la portion visible de la carte.

Dés que la vue change l'évènement OnChangeMapBounds(sender: TObject) est déclenché.

La function ScreenShot retourne un TBitmap contenant l'image de la carte

Zoom

La propriété Zoom vous permet de contrôler la définition de votre carte, elle est de type integer et est accessible en lecture/écriture

Vous avez accès aussi au propriété MaxZoom et MinZoom qui vous permettent de déterminer les limites du zoom

6

Utilisez la procedure ZoomAround(const LatLngZoom:TLatLng; const NewZoom:Integer) pour zoomer tout en restant centré sur un point précis (comme à la souris)

Le changement de zoom déclenche l'évènement OnChangeMapZoom(sender: TObject)

En positionnant la propriété DragRect sur drZoom vous pouvez sélectionner une zone avec la souris en maintenant le bouton droit enfoncé, lorsque vous relachez le bouton un zoom est effectué sur la région sélectionnée.

ZoomScaleFactor

Cette propriété vous permet d'émuler les zooms intermédiaires

// emulate zoom 16.35
map.zoom := 16;
map.zoomScaleFactor := 35;


Faites Click droit + molette pour changer ZoomScaleFactor à la souris

3

Fig. 20 ZoomScaleFactor

Vous pouvez réaliser un zoom progressif du zoom 1 jusqu'au-delà du Zoom maximal prévu par le serveur de tuiles, simplement en incrémentant zoomScaleFactor, et inversement pour dézoomer.

Fig. 21 Progressive zoom

ZoomScaleFactor peut varier de -999 à 999, si le zoom maximum n'est pas atteind 100 correspond à zoom+1 (et inversement)

7

Utilisez la procedure ZoomScaleFactorAround(const LatLngZoom:TLatLng; const NewZoomScaleFactor:Integer) pour zoomer tout en restant centré sur un point précis (comme à la souris)

La propriété NumericalZoom regroupe Zoom et ZoomScaleFactor

4
map.NumericalZoom := 15.6;

Gestion de la carte au clavier

TECNativeMap dispose des événements OnKeyUp et OnKeyDown

Exemple de code pour gérer les déplacements et le zoom avec les touches fléchées, + et -

procedure TForm.mapKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var kUp,kDown,kLeft,kRight,kCtrl : boolean;
PixelShift : integer;
begin
// KeyIsDown in uecMapUtil unit
kDown := KeyIsDown(VK_DOWN);
kLeft := KeyIsDown(VK_LEFT);
kUp := KeyIsDown(VK_UP);
kRight := KeyIsDown(VK_RIGHT);
kCtrl := KeyIsDown(VK_LCONTROL) or KeyIsDown(VK_RCONTROL);
// 40 pixels displacement
PixelShift := 40;

if kDown then
begin
if kLeft then
map.ScrollXY(PixelShift,-PixelShift)
else
if kRight then
map.ScrollXY(-PixelShift,-PixelShift)
else
map.ScrollXY(0,-PixelShift)
end
else
if kUp then
begin
if kLeft then
map.ScrollXY(PixelShift,PixelShift)
else
if kRight then
map.ScrollXY(-PixelShift,PixelShift)
else
map.ScrollXY(0,PixelShift)
end
else
if kRight then
map.ScrollXY(-PixelShift,0)
else
if kLeft then
map.ScrollXY(PixelShift,0);

// To make a move in Km you can use Move(direction,km)
// direction 0 to 359
// map.Move(90,0.1); move right 100 meters

// if CTRL we zoom in 1/10 of level
if KeyIsDown(VK_ADD) then
begin
if kCtrl then
map.ZoomScaleFactor := map.ZoomScaleFactor + 10
else
map.Zoom := map.Zoom + 1;
end
else
if KeyIsDown(VK_SUBTRACT) then
begin
if kCtrl then
map.ZoomScaleFactor := map.ZoomScaleFactor - 10
else
map.Zoom := map.Zoom - 1;
end;


end;

Adapter les markers au Zoom

Utilisez la propriété ScaleMarkerToZoom pour que la taille des markers changent en fonction du Zoom.

Fig. 22 ScaleMarkerToZoom

Sélection

La propriété Selected vous permet de sélectionner des éléments.

// select items in area
nbr_item_selected := map.Selected.ByArea(NorthEastLat,NorthEastLng,SouthWestLat,SouthWestLng);

// select items <=Max_Distance_KM to CenterPointLat,CenterPointLng
nbr_item_selected := map.Selected.ByKMDistance(CenterPointLat,CenterPointLng,Max_Distance_KM);

// loop to all selected items

var shape:TECShape

for shape in map.Selected do
begin
..
end;

En positionnant DragRect sur drSelect vous pouvez effectuer une sélection avec la souris en maintenant le bouton droit enfoncé puis en le relachant une fois la zone délimitée.

Vous pouvez redéfinir l'apparence du rectangle de sélection en utilisant les styles, exemple pour avoir une épaisseur de ligne de 10 pixels, une couleur verte et une ligne en pointillé

map.styles.addRule('#_DRAGZOOM_.line {weight:10;color:green;penStyle:dash}');

Fig. 23 sélection stylisée

Vous pouvez aussi utiliser l'outil de sélection main-libre pour entourer plus simplement vos éléments.

5

Pour déselectionner tous vos éléments utilisez map.Selected.UnSelectedAll

La liste GroupFilter permet de définir un filtre sur les groupes acceptés

// only elements from these groups will be accepted
map.Selected.groupFilter.add('group1');
map.Selected.groupFilter.add('group2');
// clear list for accept all
map.Selected.groupFilter.clear;

Vous pouvez définir votre propre filter en vous branchant sur OnSelectShape.

map.Selected.OnSelectShape := doOnSelectShape;
...
procedure TForm.doOnSelectShape(Sender: TObject; const Shape: TECShape;
var cancel: Boolean);
begin

// accept only TECShapePOI
cancel := not(Shape is TECShapePOI);
end;

Vous pouvez sélectionner / déselectionner par code n'importe quel élément au travers de sa propriété selected

// unselect
map.shapes.markers[0].selected := false;
// select
map['groupx'].pois[0].selected := true;

Pour déplacer à la souris tous les éléments sélectionnés en même temps, affectez sdmMultiShapes à la propriété ShapeDragMode de votre carte.

6
// move all seleted shapes
map.ShapeDragMode := sdmMultiShapes;
// move only the element under the mouse (default)
map.ShapeDragMode := sdmShape;

Fig. 24 Déplacer les éléments sélectionnés

Par défaut les éléments sélectionnés sont dessinés en utilisant la couleur définie pour le survol de la souris, vous pouvez ajouter une marque distinctive en vous branchant sur leur événement OnAfterDraw.

Cet exemple ajoute une étoile rouge en haut à droite des éléments sélectionnés

// when you create item you must connect like this item.OnAfterDraw := doAfterDraw

procedure TForm1.doAfterDraw(const canvas: TECCanvas; var rect: TRect; item: TECShape) ;
var size_start : integer;
begin
if assigned(item) and (item.Selected) then
begin
size_start := (item.Width div 2);
if size_start< 10 then size_start := 10;

canvas.Pen.Color := claBlack;
canvas.PenWidth(1);
canvas.Brush.Color := GetHighlightColorBy(claRed,16);

rect.Left := rect.Left + (rect.Right-rect.Left) - size_start;
rect.Top := rect.Top - (size_start div 2);
rect.Bottom := rect.Top + size_start ;

canvas.DrawStar(rect);
end;
end;

Fig. 25 3 selected items

Ou plus simplement vous pouvez définir un style.

// all shapes selected is red
map.styles.addRule(':selected {color:red}');
// enlarge the selected markers
map.styles.addRule('.marker:selected {scale:1.2}');

Vous pouvez sauvegarder la sélection dans un fichier avec SaveToFile ou dans une chaine avec toXXX

// Export of selected elements to geoJSON, GPX, KML and Text formats

map.Selected.SaveToFile('file.json');
map.Selected.SaveToFile('file.gpx');
map.Selected.SaveToFile('file.kml');
map.Selected.SaveToFile('file.txt');

json_string := map.Selected.toGeoJSON;
gpx_string := map.Selected.toGPX;
kml_string := map.Selected.toKML;
txt_string := map.Selected.toTxt;

Rotation de la carte

Disponible seulement dans la version Firemonkey

3
Placez votre composant dans un conteneur (TPanel, TRectangle) qui servira à délimiter la zone visible puis activez la propriété OverSizeForRotation

map.OverSizeForRotation := true;

// To allow or not the rotation gesture use the property EnableTouchRotation

map.EnableTouchRotation := true;

EnableTouchRotation permet d'autoriser ou non la rotation par geste.

8

Fig. 26 Rotation map

Url

La propriété Url retourne/accepte une chaine au format '#zoom/Latitude/Longitude'

// zoom 18 latitude 48.856527 longitude 2.352104
// welcome to Paris !
map.Url := '#18/48.856527/2.352104';

L'assignation d'une valeur à cette propriété déclenche l'événenement OnBeforeUrl(sender : TObject; var Url:string) qui peut vous permettre de modifier l'url, et même d'annuler le changement en retournant une chaine vide.

Vous pouvez passer une tel lien dans une InfoWindow

// welcome to Paris !
map.Shapes.InfoWindows[0].Content := 'Go to <a href="#18/48.856527/2.352104">Paris !</a>';

Fig. 27 Url Link

Si vous passez une url "classique" elle s'ouvrira dans votre navigateur par défaut.

1

Distance

La fonction DistanceFrom(const dLatitudeStart,dLongitudeStart,dLatitudeEnd,dLongitudeEnd:double):double permet de calculer la distance entre 2 points, le résultat est en Kilomètres.

Angle par rapport au Nord

La fonction Bearing(const dLatitudeStart,dLongitudeStart,dLatitudeEnd,dLongitudeEnd:double):integer vous donne l'angle, de 0° à 360°, pour la direction allant du point dLatitudeStart,dLongitudeStart au point dLatitudeEnd,dLongitudeEnd

MiniMap

Fig. 28 MiniMap

Pour afficher une mini carte navigable dans votre carte principale il vous suffit d'ajouter l'unité uecNativeMiniMap à votre fiche ainsi que les lignes suivantes.

// Delphi native map component TECNativeMap

var FMiniMap : TECNativeMiniMap;
...
// create and show minimap on Map
FMiniMap := TECNativeMiniMap.create(Map);

// for hide minimap
FMiniMap.Map := nil;

// for show
FMiniMap.Map := Map;

Vous n'avez pas à libérer votre minimap, elle le sera automatiquement lors de la destruction de la carte à laquelle elle est rattachée.

4

Vous pouvez modifier le coin d'ancrage avec la propriété ancragePosition (apTopLeft, apTopRight, apBottomLeft, apBottomRight )

XMargin et YMargin permettent d'ajuster la position par rapport aux bords

BorderColor et BorderSize modifie la couleur et taille de la bordure entourant la mini carte.

Screenshot vous permet d'obtenir une image de votre miniMap, vous devrez la libérer vous même !

Barre d'échelle

La propriétée ScaleBar de la carte permet de gérer la barre d'échelle

procedure TForm1.FormCreate(Sender: TObject);
begin
map.ScaleBar.Visible := true;
map.ScaleBar.Color := claWhite;
map.ScaleBar.SecondaryColor := claRed;
map.ScaleBar.Style := sbsBar;
map.ScaleBar.Division := sbdFour;
map.ScaleBar.Thickness := 8;
map.scalebar.opacity := 50;
end;


Les propriétés suivantes sont disponible :

Pour utiliser les propriétés AnchorPosition, Style et MeasureSystem vous devez rajouter l'unité uecMapUtil

5

property AnchorPosition: TAnchorPosition

Ancrage de la barre (apTopLeft, apTopRight, apBottomLeft, apBottomRight )

property Color: TColor

Couleur principale du texte et de la barre

property SecondaryColor: TColor

Couleur secondaire de la barre, utilisée aussi pour l'ombre

property Division : TECScaleBarDivision

Nombre de divisions (sbdNone, sbdOne, sbdFour)

property FontSize : integer

Taille du texte

property MaxWidth: integer

Longueur maximale de la barre en pixels (défaut 80)

property Style : TScaleBarStyle

Ligne ou barre (sbsLine, sbsBar)

property MeasureSystem: TMesureSystem

Système de mesure (msMetric, msImperial, msNautical) ( défaut msMetric )

property Shadow: boolean

Effet d'ombre, utilise SecondaryColor

property Thickness : integer

Épaisseur de la barre (défaut 2)

property Visible: boolean

Affiche ou non la ScaleBar (défaut false)

property XMargin: integer

Marge par rapport au bord droit ou gauche de la carte

property YMargin: integer

Marge par rapport au bord haut ou bas de la carte

property Opacity : byte

Transparence de la barre ( 0..100 )

Fig. 29 Démo Scalebar

Outil de mesure

La propriété MeasureTool du composant vous donne accès à un outil de mesure de distance et d'aire.

procedure TForm1.FormCreate(Sender: TObject);
begin
map.MeasureTool.Visible := true;
// distance
map.MeasureTool.MeasureArea := false;
// area
map.MeasureTool.MeasureArea := true;
// react to changes in distance or area
map.MeasureTool.OnChange := doChange;
end;

// fired when distance or area change
procedure TFormMeasureTool.doChange(Sender : TObject);
begin
// you can also access the values
// map.MeasureTool.Distance
// map.MeasureTool.Area
if map.MeasureTool.MeasureArea then
begin
lbDistance.Caption := 'Perimeter : '+map.MeasureTool.DistanceText;
lbArea.Caption := 'Area : '+map.MeasureTool.AreaText;
end
else
begin
lbDistance.Caption := 'Distance : '+map.MeasureTool.DistanceText;
lbArea.Caption := '';
end;

end;



Fig. 30 Distance

Fig. 31 Area

Cliquez sur la carte pour ajouter un point, faites une longue pression sur un point pour le supprimer, utilisez le drag and drop pour déplacer votre outil.

9

Consultez la demo MeasureTool pour la prise en main.

Observateur

Un observateur vous permet d'être averti lorsqu'un événement particulier à lieux que cela soit un déplacement de la carte ou d'un élément.

Cela a l'avantage de ne pas bloquer les événements principaux de la carte et des shapes tout en les démultipliant.


TNativeMapObserver = class(TObject)
public

property OnMapFree : TNotifyEvent ;
property OnMapHiResChange : TNotifyEvent ;
property OnMapActiveChange : TNotifyEvent
property OnMapAnimation : TNotifyEvent;
property OnMapResize : TNotifyEvent;
property OnMapRotation : TNotifyEvent;
property OnMapMove : TNotifyEvent;
property OnMapMouseMove : TNotifyEvent;
property OnMapMouseClick : TNotifyEvent;
property OnMapEndMove : TNotifyEvent;
property OnMapzoom : TNotifyEvent;
property OnMapLoad : TNotifyEvent;
property OnMapBounds : TNotifyEvent;
property OnMapChangeBounds : TNotifyEvent;
property OnMapTileServer : TNotifyEvent;
property OnMapAddRoute : TNotifyEvent;
property OnMapErrorRoute : TNotifyEvent;
property OnMapChangeRoute : TNotifyEvent;
property OnMapPaint : TNotifyEvent;
property OnShapesPaint : TNotifyEvent;
property OnMapShapeDescription : TNotifyEvent;
property OnMapShapeProperties : TNotifyEvent;
property OnMapShapeHint : TNotifyEvent;
property OnMapShapeClick : TNotifyEvent;
property OnMapShapeMove : TNotifyEvent;
property OnMapShapeDblClick : TNotifyEvent;
property OnMapShapeMouseOut : TNotifyEvent;
property OnMapShapeMouseOver : TNotifyEvent;
property OnMapShapeDrag : TNotifyEvent;
property OnMapShapeDragEnd : TNotifyEvent;
property OnMapShapePathChange : TNotifyEvent;
property OnMapShapeRightClick : TNotifyEvent;
property OnMapShapesChange : TNotifyEvent;

Vous pouvez enregistrer autant d'observateurs que vous le souhaitez.

FObserver1 := TNativeMapObserver.Create;
FObserver1.OnMapResize := Map_Resize;
FObserver1.OnMapMove := Map_Move;

FObserver2 := TNativeMapObserver.Create;
FObserver2.OnMapBounds := Map_Bounds;
FObserver2.OnMapTileServer := Map_TileServer;
FObserver2.OnMapRotation := Map_Rotate;

// attach observer
map.attach(FObserver1);
map.attach(FObserver2);
...
// detach
map.detach(FObserver1);
map.detach(FObserver2);
...
FObserver1.free;
FObserver2.free;

Les layers utilisent ce système pour réagir au changement de position.

Aller à la page
Réalisé avec la version gratuite pour les particuliers d'Help&Web