Summary
- Bing
- Here
- MapBox
- TomTom
- PTV Group
- List of predefined servers
- WMS tile server
- Use your own tile server
- ColorFilter
- Overlay tiles
- Vector Tiles
- Connection to a vector tile server
- Positioning on the map
- Graticule
- Reacting to the change in position
- Zoom
- ZoomScaleFactor
- Keyboard map management
- Adapt the markers to the Zoom
- Selection
- Map rotation
- Url
- Distance
- Angle to the North
- MiniMap
- Scale bar
- Measurement tool
- Observer
TECNativeMap is available in VCL and Firemonkey (Windows , Mac OS X, iOs and Android) for the same price !
you access an offline mode, not using the Google Maps service and other Bing Maps lets you keep control over your data.
test a demonstration for Android
1TECNativeMap allows you to use OpenStreetMap maps, Google, MapBox, OpenCycleMap, OPNV, TomTom etc, and manage your own components to integrate into it.
To select a map provider use the property TileServer
To use Google Tiles you need to enter your API key in GoogleKey, go to Google's platform to generate it.
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" }'+
']}]';
Bing
By filling in the BingKey property with your Bing key you can use Bing Maps tiles ( tsBingRoad, tsBingAerial and tsBingAerialLabels )
map.BingKey := YOUR_BING_KEY
map.TileServer := tsBingRoad;
Here
By filling the HereApiKey propertie You can use the Here tiles
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';
MapBox
To use the tiles from MapBox ( tsMapBoxSatellite, tsMapBoxStreets,tsMapBoxStreetsSatellite,tsMapBoxStreetsBasic ) enter your token in MapBoxToken.
You must also specify a tile size of 512
1map.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';
TomTom
To use TomTom tiles ( tsTomTomBasic, tsTomTomHybrid, tsTomTomNight, tsTomTomIncident, tsTomTomFlow ) you must obtain a key and fill in the TomTomKey property of your map.
map.TileServer := tsTomTomBasic;
// add overlay tiles for TomTom Hybrid
map.AddOverlayTileServer(tsTomTomHybrid);
// mandatory, reset api key for overlay
map.TomTomKey := Your_TomTomKey;
For tsTomTomIncident and tsTomTomFlow you have the choice between 4 styles
...
// 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
You must obtain your api key to use these maps.
You can use PTV tiles as a base map or as an overlay on top of any background map..
property ApiKey: string
property BaseMapLayer: TPTVBaseMapLayer
Choice of base map type (none, amber, blackmarble, classic, gravelpit, sandbox,silica, silkysand, satellite)none to switch back to a TileServer-managed base map other than PTV
2property ForegroundLayers: TPTVForegroundLayers
If you do not include background the base map will not be displayed.
3If you use the satellite background map, you must use OverlayLayers to embed PTV layers.
2property OverlayLayers: TPTVForegroundLayers
property PTV_COPYRIGHT: string
property VehicleType: TPTVvehicleType
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;
You can display your map background in grayscale with map.Grayscale := true
1List of predefined servers
If you try to download tiles from the internet and there is no connection, the OnErrorConnection event in your map is triggered.
OnlyLocal is then set to true to prevent any connection attempt, when the connection comes back you will have to set OnlyLocal back to false, this will not be done automatically.
1WMS tile server
You can use a WMS service to display your tiles.
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);
Use your own tile server
In addition to the previous maps you can use any other provider using the same 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
This property allows you to modify/change certain colors of your tiles.
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;
// 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;
With Firemonkey you can also define certain colors that will be kept or that you can replace without them being modified by the filter.
...
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;
Overlay tiles
You can use several server of tiles to display above your base map.
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;
You can still use a stream.
procedure
TForm.getOverlayTileStream(var TileStream:
TMemoryStream;const x, y, z:
integer);
begin
// here fill the stream with your
tile
end;
...
map.AddOverlayStreamTiles(getOverlayTileStream);
Or directly using a transparent predefined server as tsHereFlow or tsHereTruckTransparent
// mix Bing
Aerial Labels and Here Flow
map.TileServer := tsBingAerialLabels;
map.AddOverlayTileServer(tsHereFlow);
As another example, use the services of OpenRailWayMap to display railroad facilities.
// standard style
o := map.AddOverlayTileServer(tsOpenRailWayMap);
// other styles
o.MapStyle := 'maxspeed';
o.MapStyle := 'signals';
o.MapStyle := 'electrification';
o.MapStyle := 'gauge';
With VCL your overlay should use pngs, under FMX you can use the opacity property.
4
var
overlay:TECOverlayTileLayer;
...
// overlay clouds
tiles
overlay := map.AddOverlayTiles(GetWeatherTile);
// set opacity 0..1
overlay.opacity := 0.5;
Use RemoveAllOverlayTiles to delete all overlays
You can also embed an image if it is to scale
2Vector Tiles
Starting with version 5.5 (October 2024), TECNativeMap offers minimalist support for vector tiles as defined by MapBox
As it stands, it's a prototype that can't be used in production, and only very partially covers style specifications. 3D support is not envisaged in the short or medium term.
2Connection to a vector tile server
All you have to do is pass the url of your style (in MapLibre json format), if necessary you'll also need to enter your api key.
map.setVMTTileServer('https://api.maptiler.com/maps/basic-v2/style.json?key=YOUR_API_KEY');
You can also connect manually as follows
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;
You can browse through all the styles, for example here we'll fill a listbox
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;
Positioning on the map
You can determine the coordinates of the center of the map through the Latitude and Longitude properties, they are of type double and accessible in read/writeYou can directly modify the coordinates through the procedure setCenter(const dlatitude,dlongitude:double)
PanTo(lat,lng) is equivalent but a scroll will be performed if the displacement is minimal otherwise we go directly to the new position as setCenter
Utilisez Move(direction,DistanceKM) to move in a direction varying from 0 to 359° and over a distance in 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;
Mouse position
The latitude and longitude of the point under the mouse cursor are returned by the property MouseLatLng
You can connect on the event OnMapMouseMove to know in time real your position
Graticule
Displays a grid showing latitudes and longitudes.
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
Reacting to the change in position
When the center of the map is moved, This either by code or the mouse directly, the event OnMapMove(sender: Tobject;const dLatitude,dLongitude:double) is raised
Sender represents the ECNativeMap component that has changed, dLatitude and dLongitude the new coordinates, who are also accessible through Latitude and Longitude
When the map starts to move the event OnMapDragStart is raised, then OnMapDrag while the move and OnMapDragEnd at the end of displacement.
Area displayed
You can determine the coordinates of North East point (top-right) and point South West (lower-left) of the displayed area by the component through the properties NorthEastLatitude, NorthEastLongitude, SouthWestLatitude and SouthWestLongitude, they are double and accessible read-only.
The procedure BoundingBox(maxLatitude,maxLongitude,minLatitude,minLatitude) limit the accessible area of your map, the event OnOutOfBounds is raised if you attempt to access a restricted area.
A call to BoundinBox without parameter throws limitations.
5The procedure fitBounds(const dLatlo,dLnglo,dLathi,dLnghi:double) allows you to adjust the view to the coordinates passed.
You can also pass it an array containing groups and thus get a view on all elements.
6the procedure boundingCoordinates(const lat, lng, radius: double; var latSW, lngSW,latNE, lngNE: double); Returns the coordinates of a rectangular area on the basis of the focal point and a distance in km.
The function ContainsLatLng(var dLatitude,dLongitude:double):boolean tells you if the dLatitude, dLongitude is in the visible portion of the map.
As soon as the view changes the event OnChangeMapBounds(sender: TObject) is raised.
The function ScreenShot Returns an integer containing the image of the map
Zoom
The Zoom property allows you to control the definition of your card, it is of type integer and is accessible in read/write
You have access also to the MaxZoom and property MinZoom that allow you to determine the limits of the zoom
7Use the ZoomAround(const LatLngZoom:TLatLng; const NewZoom:Integer) procedure to zoom while remaining focused on a specific point (as in mouse)
The zoom change triggers the event OnChangeMapZoom(sender: TObject)
By setting the DragRect property on drZoom you can select an area with the mouse by holding the right button, when you release the button zoom is performed on the selected region.
ZoomScaleFactor
This property allows you to emulate the intermediate zooms
const
Data_Uri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==';
map.Shapes.Markers[0].filename := Data_Uri;
Make right Click + scroll wheel to change ZoomScaleFactor
3You can zoom in progressively from zoom 1 to beyond the maximum zoom provided by the tile server, simply by incrementing zoomScaleFactor, and vice versa to zoom out.
ZoomScaleFactor can vary from -999 to 999, if the maximum zoom is not reached 100 corresponds to zoom+1 (and conversely)
8Use the procedure ZoomScaleFactorAround (const LatLngZoom:TLatLng; const NewZoomScaleFactor:Integer) to zoom while remaining focused on a specific point (as with mouse)
The NumericalZoom property groups Zoom and ZoomScaleFactor
4Keyboard map management
TECNativeMap has OnKeyUp and OnKeyDown events
Example of code to manage movement and zoom with the arrow keys, + and -.
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;
Adapt the markers to the Zoom
Use the ScaleMarkerToZoom property to resize markers depending of Zoom.
Selection
The Selected property allows you to select items.
// 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;
By setting DragRect to drSelect you can make a selection with the mouse by holding the right button and release once the area is delimited.
You can redefine the appearance of the selection rectangle using styles, example to have a line of 10 pixels width, green color, and a dotted line
map.styles.addRule('#_DRAGZOOM_.line {weight:10;color:green;penStyle:dash}');You can also use the freehand selection tool to simply surround your elements.
5To deselect all your items use map.Selected.UnSelectedAll
The GroupFilter list allows to define a filter on the groups allowed
map.Selected.groupFilter.add('group1');
map.Selected.groupFilter.add('group2');
// clear list for accept all
map.Selected.groupFilter.clear;
You can define your own filter by connecting you on OnSelectShape.
...
procedure TForm.doOnSelectShape(Sender: TObject; const Shape: TECShape;
var cancel: Boolean);
begin
// accept only TECShapePOI
cancel := not(Shape is TECShapePOI);
end;
You can select / deselect any element by code through its selected property
map.shapes.markers[0].selected := false;
// select
map['groupx'].pois[0].selected := true;
To move all selected elements at once with the mouse, assign sdmMultiShapes to your map's ShapeDragMode property.
6map.ShapeDragMode := sdmMultiShapes;
// move only the element under the mouse (default)
map.ShapeDragMode := sdmShape;
Selected items are drawn using the color HoverColor, you can add a distinguishing mark by connecting you on their OnAfterDraw event.
This example adds a red star in the upper right corner of selected items
// 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;
Or simply you can set a style.
map.styles.addRule(':selected {color:red}');
// enlarge the selected markers
map.styles.addRule('.marker:selected {scale:1.2}');
You can save the selection in a file with SaveToFile or in a string with toXXX
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;
Map rotation
Available only in the version Firemonkey
3map.OverSizeForRotation :=
true;
// To allow or not the rotation
gesture use the property EnableTouchRotation
map.EnableTouchRotation := true;
EnableTouchRotation Enable rotation by gesture.
9Url
The Url property returns / accepts a string in the format '#zoom/Latitude/Longitude'
// zoom 18 latitude 48.856527
longitude 2.352104
// welcome to Paris !
map.Url := '#18/48.856527/2.352104';
Assigning a value to this property raises the event OnBeforeUrl(sender : TObject; var Url:string) that can allow you to change the url, and even to cancel the change by returning an empty string.
You can pass a such link in a InfoWindow
// welcome to Paris !
map.Shapes.InfoWindows[0].Content := 'Go to
<a href="#18/48.856527/2.352104">Paris
!</a>';
If you pass a 'classical' url it will open in your default browser.
1Distance
The function DistanceFrom(const dLatitudeStart,dLongitudeStart,dLatitudeEnd,dLongitudeEnd:double):double to calculate the distance between 2 points, the result is in kilometers.
Angle to the North
The function Bearing(const dLatitudeStart,dLongitudeStart,dLatitudeEnd,dLongitudeEnd:double):integer gives you the angle, from 0 ° to 360 ° for direction from the point dLatitudeStart,dLongitudeStart to the point dLatitudeEnd,dLongitudeEnd
MiniMap
To display a mini map in your main card simply add the uecNativeMiniMap unit to your listing and add the following lines.
// 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;
You do not have to release your minimap, It will be automatically during the destruction of the card to which it is attached.
4You can change the corner of anchor with the property ancragePosition (apTopLeft, apTopRight, apBottomLeft, apBottomRight )
XMargin and YMargin allow you to adjust the position relative to the edges
BorderColor and BorderSize changes the color and size of the border surrounding the mini map.
Screenshot allows you to get an image of your miniMap, you will have to release it yourself!
Scale bar
The ScaleBar property of the map is used to manage the scale bar.
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;
The following properties are available :
To use the AnchorPosition, Style and MeasureSystem properties, you must add the uecMapUtil unit.
5property AnchorPosition: TAnchorPosition
property Color: TColor
property SecondaryColor: TColor
property Division : TECScaleBarDivision
property FontSize : integer
property MaxWidth: integer
property Style : TScaleBarStyle
property MeasureSystem: TMesureSystem
property Shadow: boolean
property Thickness : integer
property Visible: boolean
property XMargin: integer
property YMargin: integer
property Opacity : byte
Measurement tool
The component's MeasureTool property gives you access to a distance and area measurement tool.
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;
Click on the map to add a point, long-press a point to delete it, drag and drop to move your tool.
10Take a look at the MeasureTool demo to get started.
Observer
An observer allows you to be notified when events is fired in map or in shape.
This has the advantage of not to block the main events of the map and the shapes.
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;
You can add as many observers as you want.
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;
The layers using observers to react to the change of position.