0
# Location & Maps
1
2
Geolocation services, background location tracking, geofencing capabilities, and maps integration for location-aware applications.
3
4
## Capabilities
5
6
### Geolocation
7
8
Access device location services for current position and continuous location tracking with configurable accuracy options.
9
10
```typescript { .api }
11
/**
12
* Geographic coordinates interface
13
*/
14
interface Coordinates {
15
/** Latitude in decimal degrees */
16
latitude: number;
17
/** Longitude in decimal degrees */
18
longitude: number;
19
/** Altitude in meters above the reference ellipsoid */
20
altitude: number;
21
/** Accuracy of latitude and longitude coordinates in meters */
22
accuracy: number;
23
/** Accuracy of altitude coordinate in meters */
24
altitudeAccuracy: number;
25
/** Direction of travel in degrees (0-359.99) */
26
heading: number;
27
/** Current ground speed in meters per second */
28
speed: number;
29
}
30
31
/**
32
* Geographic position with timestamp
33
*/
34
interface Geoposition {
35
/** Geographic coordinates */
36
coords: Coordinates;
37
/** Timestamp when location was retrieved */
38
timestamp: number;
39
}
40
41
/**
42
* Position error information
43
*/
44
interface PositionError {
45
/** Error code (1: PERMISSION_DENIED, 2: POSITION_UNAVAILABLE, 3: TIMEOUT) */
46
code: number;
47
/** Error message */
48
message: string;
49
}
50
51
/**
52
* Geolocation options
53
*/
54
interface GeolocationOptions {
55
/** Enable high accuracy mode (uses GPS) */
56
enableHighAccuracy?: boolean;
57
/** Timeout for location request in milliseconds */
58
timeout?: number;
59
/** Maximum age of cached position in milliseconds */
60
maximumAge?: number;
61
}
62
63
/**
64
* Geolocation class for location services
65
*/
66
class Geolocation {
67
/**
68
* Get current device position
69
* @param options Location options
70
* @returns Promise resolving to current Geoposition
71
*/
72
static getCurrentPosition(options?: GeolocationOptions): Promise<Geoposition>;
73
74
/**
75
* Watch device position changes
76
* @param options Location options
77
* @returns Observable emitting Geoposition updates
78
*/
79
static watchPosition(options?: GeolocationOptions): Observable<Geoposition>;
80
}
81
```
82
83
**Usage Examples:**
84
85
```typescript
86
import { Geolocation, GeolocationOptions } from 'ionic-native';
87
88
// Get current location
89
async function getCurrentLocation() {
90
const options: GeolocationOptions = {
91
enableHighAccuracy: true,
92
timeout: 10000,
93
maximumAge: 60000
94
};
95
96
try {
97
const position = await Geolocation.getCurrentPosition(options);
98
99
console.log('Current position:');
100
console.log('Latitude:', position.coords.latitude);
101
console.log('Longitude:', position.coords.longitude);
102
console.log('Accuracy:', position.coords.accuracy, 'meters');
103
104
return {
105
lat: position.coords.latitude,
106
lng: position.coords.longitude,
107
accuracy: position.coords.accuracy
108
};
109
} catch (error) {
110
console.error('Error getting location:', error);
111
throw error;
112
}
113
}
114
115
// Watch position changes for navigation
116
function startLocationTracking() {
117
const options: GeolocationOptions = {
118
enableHighAccuracy: true,
119
timeout: 5000,
120
maximumAge: 0
121
};
122
123
return Geolocation.watchPosition(options).subscribe(
124
(position) => {
125
console.log('Position update:', {
126
lat: position.coords.latitude,
127
lng: position.coords.longitude,
128
accuracy: position.coords.accuracy,
129
speed: position.coords.speed,
130
heading: position.coords.heading,
131
timestamp: new Date(position.timestamp)
132
});
133
134
// Update map marker
135
updateMapPosition(position.coords);
136
137
// Log movement if speed > 0
138
if (position.coords.speed > 0) {
139
logMovement(position);
140
}
141
},
142
(error) => {
143
console.error('Location error:', error);
144
handleLocationError(error);
145
}
146
);
147
}
148
149
// Distance calculation between two points
150
function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number) {
151
const R = 6371e3; // Earth's radius in meters
152
const φ1 = lat1 * Math.PI/180;
153
const φ2 = lat2 * Math.PI/180;
154
const Δφ = (lat2-lat1) * Math.PI/180;
155
const Δλ = (lon2-lon1) * Math.PI/180;
156
157
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
158
Math.cos(φ1) * Math.cos(φ2) *
159
Math.sin(Δλ/2) * Math.sin(Δλ/2);
160
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
161
162
return R * c; // Distance in meters
163
}
164
165
// Location-based features
166
async function findNearbyPlaces(radius: number = 1000) {
167
try {
168
const position = await getCurrentLocation();
169
170
// Find nearby places within radius
171
const nearbyPlaces = await searchNearbyPlaces(
172
position.lat,
173
position.lng,
174
radius
175
);
176
177
return nearbyPlaces;
178
} catch (error) {
179
console.error('Error finding nearby places:', error);
180
return [];
181
}
182
}
183
```
184
185
### Background Geolocation
186
187
Continuous location tracking that works when the app is in the background for tracking and navigation use cases.
188
189
```typescript { .api }
190
/**
191
* Background geolocation configuration
192
*/
193
interface BackgroundGeolocationConfig {
194
/** Desired accuracy in meters (iOS: kCLLocationAccuracyXXX) */
195
desiredAccuracy?: number;
196
/** Stationary radius in meters */
197
stationaryRadius?: number;
198
/** Distance filter in meters */
199
distanceFilter?: number;
200
/** Enable debug mode */
201
debug?: boolean;
202
/** Location timeout in milliseconds */
203
interval?: number;
204
/** Fastest location interval in milliseconds */
205
fastestInterval?: number;
206
/** Activity type for iOS (AutomotiveNavigation, Navigation, Fitness, Other) */
207
activityType?: string;
208
/** Defer location updates until later */
209
deferLocationUpdates?: boolean;
210
/** Stop on terminate */
211
stopOnTerminate?: boolean;
212
/** Start on boot */
213
startOnBoot?: boolean;
214
/** Start in foreground */
215
startForeground?: boolean;
216
/** Notification title (Android) */
217
notificationTitle?: string;
218
/** Notification text (Android) */
219
notificationText?: string;
220
/** Notification icon (Android) */
221
notificationIcon?: string;
222
/** Location provider (GPS_PROVIDER, NETWORK_PROVIDER, PASSIVE_PROVIDER) */
223
locationProvider?: number;
224
}
225
226
/**
227
* Background location data
228
*/
229
interface BackgroundLocation {
230
/** Latitude */
231
latitude: number;
232
/** Longitude */
233
longitude: number;
234
/** Accuracy in meters */
235
accuracy: number;
236
/** Altitude in meters */
237
altitude: number;
238
/** Speed in m/s */
239
speed: number;
240
/** Bearing in degrees */
241
bearing: number;
242
/** Location timestamp */
243
time: number;
244
/** Location provider used */
245
provider: string;
246
}
247
248
/**
249
* BackgroundGeolocation class for continuous location tracking
250
*/
251
class BackgroundGeolocation {
252
/**
253
* Configure background location tracking
254
* @param options Configuration options
255
* @returns Observable emitting location updates
256
*/
257
static configure(options: BackgroundGeolocationConfig): Observable<BackgroundLocation>;
258
259
/**
260
* Start background location tracking
261
*/
262
static start(): void;
263
264
/**
265
* Stop background location tracking
266
*/
267
static stop(): void;
268
269
/**
270
* Check if location services are enabled
271
* @returns Promise resolving to boolean
272
*/
273
static isLocationEnabled(): Promise<boolean>;
274
275
/**
276
* Show app-specific settings
277
*/
278
static showAppSettings(): void;
279
280
/**
281
* Show location settings
282
*/
283
static showLocationSettings(): void;
284
285
/**
286
* Check plugin status
287
* @returns Promise resolving to status object
288
*/
289
static checkStatus(): Promise<any>;
290
291
/**
292
* Get stationary location
293
* @returns Promise resolving to location
294
*/
295
static getStationaryLocation(): Promise<BackgroundLocation>;
296
297
/**
298
* Get plugin log entries
299
* @param limit Maximum number of entries
300
* @returns Promise resolving to log entries
301
*/
302
static getLogEntries(limit: number): Promise<any>;
303
}
304
```
305
306
**Usage Examples:**
307
308
```typescript
309
import { BackgroundGeolocation, BackgroundGeolocationConfig } from 'ionic-native';
310
311
// Configure and start background tracking
312
function startBackgroundTracking() {
313
const config: BackgroundGeolocationConfig = {
314
desiredAccuracy: 10,
315
stationaryRadius: 20,
316
distanceFilter: 30,
317
debug: false,
318
interval: 60000,
319
fastestInterval: 5000,
320
activitiesInterval: 300000,
321
activityType: 'AutomotiveNavigation',
322
stopOnTerminate: false,
323
startOnBoot: true,
324
startForeground: false,
325
notificationTitle: 'Location Tracking',
326
notificationText: 'Your location is being tracked',
327
locationProvider: 1 // GPS_PROVIDER
328
};
329
330
BackgroundGeolocation.configure(config).subscribe(
331
(location) => {
332
console.log('Background location update:', {
333
latitude: location.latitude,
334
longitude: location.longitude,
335
accuracy: location.accuracy,
336
speed: location.speed,
337
timestamp: new Date(location.time)
338
});
339
340
// Save location to local storage or send to server
341
saveLocationUpdate(location);
342
},
343
(error) => {
344
console.error('Background location error:', error);
345
}
346
);
347
348
// Start tracking
349
BackgroundGeolocation.start();
350
}
351
352
// Trip tracking functionality
353
class TripTracker {
354
private trackingSubscription: any;
355
private tripData: BackgroundLocation[] = [];
356
357
async startTrip() {
358
try {
359
const isEnabled = await BackgroundGeolocation.isLocationEnabled();
360
if (!isEnabled) {
361
BackgroundGeolocation.showLocationSettings();
362
return;
363
}
364
365
const config: BackgroundGeolocationConfig = {
366
desiredAccuracy: 10,
367
distanceFilter: 10,
368
interval: 5000,
369
debug: true,
370
notificationTitle: 'Trip in Progress',
371
notificationText: 'Recording your journey'
372
};
373
374
this.trackingSubscription = BackgroundGeolocation.configure(config).subscribe(
375
(location) => {
376
this.tripData.push(location);
377
this.updateTripStats(location);
378
}
379
);
380
381
BackgroundGeolocation.start();
382
console.log('Trip started');
383
} catch (error) {
384
console.error('Failed to start trip:', error);
385
}
386
}
387
388
stopTrip() {
389
if (this.trackingSubscription) {
390
this.trackingSubscription.unsubscribe();
391
}
392
393
BackgroundGeolocation.stop();
394
395
const tripSummary = this.calculateTripSummary();
396
console.log('Trip completed:', tripSummary);
397
398
return tripSummary;
399
}
400
401
private updateTripStats(location: BackgroundLocation) {
402
// Calculate distance, speed, etc.
403
if (this.tripData.length > 1) {
404
const prevLocation = this.tripData[this.tripData.length - 2];
405
const distance = this.calculateDistance(
406
prevLocation.latitude, prevLocation.longitude,
407
location.latitude, location.longitude
408
);
409
410
console.log(`Distance since last point: ${distance.toFixed(2)}m`);
411
}
412
}
413
414
private calculateTripSummary() {
415
if (this.tripData.length < 2) {
416
return { distance: 0, duration: 0, avgSpeed: 0 };
417
}
418
419
let totalDistance = 0;
420
for (let i = 1; i < this.tripData.length; i++) {
421
const prev = this.tripData[i - 1];
422
const curr = this.tripData[i];
423
424
totalDistance += this.calculateDistance(
425
prev.latitude, prev.longitude,
426
curr.latitude, curr.longitude
427
);
428
}
429
430
const startTime = this.tripData[0].time;
431
const endTime = this.tripData[this.tripData.length - 1].time;
432
const duration = (endTime - startTime) / 1000; // seconds
433
const avgSpeed = totalDistance / duration; // m/s
434
435
return {
436
distance: totalDistance,
437
duration,
438
avgSpeed,
439
points: this.tripData.length
440
};
441
}
442
443
private calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number) {
444
// Haversine formula implementation
445
const R = 6371e3;
446
const φ1 = lat1 * Math.PI/180;
447
const φ2 = lat2 * Math.PI/180;
448
const Δφ = (lat2-lat1) * Math.PI/180;
449
const Δλ = (lon2-lon1) * Math.PI/180;
450
451
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
452
Math.cos(φ1) * Math.cos(φ2) *
453
Math.sin(Δλ/2) * Math.sin(Δλ/2);
454
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
455
456
return R * c;
457
}
458
}
459
```
460
461
### Geofencing
462
463
Set up geographic boundaries and receive notifications when entering or leaving defined areas.
464
465
```typescript { .api }
466
/**
467
* Geofence configuration options
468
*/
469
interface GeofenceOptions {
470
/** Unique geofence identifier */
471
id: string;
472
/** Latitude of geofence center */
473
latitude: number;
474
/** Longitude of geofence center */
475
longitude: number;
476
/** Radius in meters */
477
radius: number;
478
/** Transition types to monitor (1: ENTER, 2: EXIT, 3: BOTH) */
479
transitionType: number;
480
/** Notification configuration */
481
notification?: {
482
/** Notification ID */
483
id?: number;
484
/** Notification title */
485
title?: string;
486
/** Notification text */
487
text?: string;
488
/** Small icon */
489
smallIcon?: string;
490
/** Large icon */
491
icon?: string;
492
/** Open app on click */
493
openAppOnClick?: boolean;
494
/** Vibration pattern */
495
vibrate?: number[];
496
/** Data payload */
497
data?: any;
498
};
499
}
500
501
/**
502
* Geofence transition event
503
*/
504
interface GeofenceTransition {
505
/** Geofence ID */
506
fenceKey: string;
507
/** Transition type (ENTER or EXIT) */
508
transitionType: string;
509
/** Device location when transition occurred */
510
location: {
511
latitude: number;
512
longitude: number;
513
accuracy: number;
514
speed: number;
515
altitude: number;
516
};
517
}
518
519
/**
520
* Geofence class for location-based triggers
521
*/
522
class Geofence {
523
/**
524
* Initialize geofencing service
525
* @returns Promise indicating initialization completion
526
*/
527
static initialize(): Promise<any>;
528
529
/**
530
* Add or update geofences
531
* @param geofences Array of geofence configurations
532
* @returns Promise indicating operation completion
533
*/
534
static addOrUpdate(geofences: GeofenceOptions[]): Promise<any>;
535
536
/**
537
* Remove geofences by ID
538
* @param geofenceIds Array of geofence IDs to remove
539
* @returns Promise indicating removal completion
540
*/
541
static remove(geofenceIds: string[]): Promise<any>;
542
543
/**
544
* Remove all geofences
545
* @returns Promise indicating removal completion
546
*/
547
static removeAll(): Promise<any>;
548
549
/**
550
* Get list of watched geofences
551
* @returns Promise resolving to array of geofence IDs
552
*/
553
static getWatched(): Promise<string[]>;
554
555
/**
556
* Observable for geofence transition events
557
* @returns Observable emitting GeofenceTransition events
558
*/
559
static onTransitionReceived(): Observable<GeofenceTransition>;
560
561
/**
562
* Observable for notification click events
563
* @returns Observable emitting notification click events
564
*/
565
static onNotificationClicked(): Observable<any>;
566
}
567
```
568
569
**Usage Examples:**
570
571
```typescript
572
import { Geofence, GeofenceOptions } from 'ionic-native';
573
574
// Initialize geofencing service
575
async function initializeGeofencing() {
576
try {
577
await Geofence.initialize();
578
console.log('Geofencing initialized');
579
580
// Set up event listeners
581
setupGeofenceListeners();
582
} catch (error) {
583
console.error('Geofencing initialization failed:', error);
584
}
585
}
586
587
// Set up geofence event listeners
588
function setupGeofenceListeners() {
589
// Listen for geofence transitions
590
Geofence.onTransitionReceived().subscribe((transition) => {
591
console.log('Geofence transition:', {
592
fence: transition.fenceKey,
593
type: transition.transitionType,
594
location: transition.location
595
});
596
597
handleGeofenceTransition(transition);
598
});
599
600
// Listen for notification clicks
601
Geofence.onNotificationClicked().subscribe((notificationData) => {
602
console.log('Geofence notification clicked:', notificationData);
603
handleNotificationClick(notificationData);
604
});
605
}
606
607
// Create geofences for important locations
608
async function createLocationGeofences() {
609
const geofences: GeofenceOptions[] = [
610
{
611
id: 'home',
612
latitude: 37.7749,
613
longitude: -122.4194,
614
radius: 100,
615
transitionType: 3, // Both enter and exit
616
notification: {
617
id: 1,
618
title: 'Home',
619
text: 'Welcome home!',
620
openAppOnClick: true,
621
vibrate: [1000, 1000, 1000],
622
data: { type: 'home', action: 'arrived' }
623
}
624
},
625
{
626
id: 'work',
627
latitude: 37.7849,
628
longitude: -122.4094,
629
radius: 200,
630
transitionType: 1, // Enter only
631
notification: {
632
id: 2,
633
title: 'Work',
634
text: 'You have arrived at work',
635
openAppOnClick: false,
636
data: { type: 'work', action: 'checkin' }
637
}
638
},
639
{
640
id: 'gym',
641
latitude: 37.7649,
642
longitude: -122.4294,
643
radius: 50,
644
transitionType: 3, // Both
645
notification: {
646
id: 3,
647
title: 'Gym',
648
text: 'Time for your workout!',
649
openAppOnClick: true,
650
data: { type: 'gym', action: 'workout' }
651
}
652
}
653
];
654
655
try {
656
await Geofence.addOrUpdate(geofences);
657
console.log('Geofences created successfully');
658
659
const watched = await Geofence.getWatched();
660
console.log('Currently watched geofences:', watched);
661
} catch (error) {
662
console.error('Failed to create geofences:', error);
663
}
664
}
665
666
// Handle geofence transitions
667
function handleGeofenceTransition(transition: GeofenceTransition) {
668
const { fenceKey, transitionType, location } = transition;
669
670
switch (fenceKey) {
671
case 'home':
672
if (transitionType === 'ENTER') {
673
// Arrived home
674
console.log('Welcome home!');
675
setHomeMode(true);
676
} else if (transitionType === 'EXIT') {
677
// Left home
678
console.log('Left home');
679
setHomeMode(false);
680
}
681
break;
682
683
case 'work':
684
if (transitionType === 'ENTER') {
685
// Arrived at work
686
console.log('Checking in at work');
687
checkInAtWork(location);
688
}
689
break;
690
691
case 'gym':
692
if (transitionType === 'ENTER') {
693
// Entered gym
694
console.log('Starting workout session');
695
startWorkoutSession();
696
} else if (transitionType === 'EXIT') {
697
// Left gym
698
console.log('Ending workout session');
699
endWorkoutSession();
700
}
701
break;
702
}
703
}
704
705
// Dynamic geofence management
706
class GeofenceManager {
707
private activeGeofences: Set<string> = new Set();
708
709
async addTemporaryGeofence(id: string, lat: number, lng: number, radius: number, durationMinutes: number) {
710
const geofence: GeofenceOptions = {
711
id,
712
latitude: lat,
713
longitude: lng,
714
radius,
715
transitionType: 3,
716
notification: {
717
title: 'Temporary Alert',
718
text: `You are near ${id}`,
719
openAppOnClick: true
720
}
721
};
722
723
await Geofence.addOrUpdate([geofence]);
724
this.activeGeofences.add(id);
725
726
// Auto-remove after duration
727
setTimeout(async () => {
728
await this.removeGeofence(id);
729
}, durationMinutes * 60 * 1000);
730
}
731
732
async removeGeofence(id: string) {
733
if (this.activeGeofences.has(id)) {
734
await Geofence.remove([id]);
735
this.activeGeofences.delete(id);
736
console.log(`Geofence ${id} removed`);
737
}
738
}
739
740
async clearAllGeofences() {
741
await Geofence.removeAll();
742
this.activeGeofences.clear();
743
console.log('All geofences cleared');
744
}
745
746
getActiveGeofences(): string[] {
747
return Array.from(this.activeGeofences);
748
}
749
}
750
```
751
752
### Google Maps Integration
753
754
Integrate Google Maps with native map functionality and custom controls.
755
756
```typescript { .api }
757
/**
758
* Google Map configuration options
759
*/
760
interface GoogleMapOptions {
761
/** Map center coordinates */
762
center?: { lat: number; lng: number; };
763
/** Initial zoom level */
764
zoom?: number;
765
/** Map type (MAP_TYPE_NORMAL, MAP_TYPE_ROADMAP, MAP_TYPE_SATELLITE, MAP_TYPE_HYBRID, MAP_TYPE_TERRAIN) */
766
mapType?: string;
767
/** Enable user location */
768
myLocationEnabled?: boolean;
769
/** Show my location button */
770
myLocationButtonEnabled?: boolean;
771
/** Enable indoor maps */
772
indoorEnabled?: boolean;
773
/** Show compass */
774
compassEnabled?: boolean;
775
/** Show zoom controls */
776
zoomControlsEnabled?: boolean;
777
/** Allow map rotation */
778
rotateGesturesEnabled?: boolean;
779
/** Allow map scrolling */
780
scrollGesturesEnabled?: boolean;
781
/** Allow map tilting */
782
tiltGesturesEnabled?: boolean;
783
/** Allow zoom gestures */
784
zoomGesturesEnabled?: boolean;
785
/** Map padding */
786
padding?: { top: number; right: number; bottom: number; left: number; };
787
}
788
789
/**
790
* Google Map instance interface
791
*/
792
interface GoogleMapObject {
793
/**
794
* Add marker to map
795
* @param options Marker options
796
* @returns Promise resolving to marker instance
797
*/
798
addMarker(options: MarkerOptions): Promise<any>;
799
800
/**
801
* Move camera to position
802
* @param target Camera target options
803
* @returns Promise indicating animation completion
804
*/
805
animateCamera(target: CameraPosition): Promise<any>;
806
807
/**
808
* Move camera to position instantly
809
* @param target Camera target options
810
*/
811
moveCamera(target: CameraPosition): void;
812
813
/**
814
* Get current camera position
815
* @returns Promise resolving to current camera position
816
*/
817
getCameraPosition(): Promise<CameraPosition>;
818
819
/**
820
* Set map bounds
821
* @param bounds Array of coordinates defining bounds
822
* @returns Promise indicating completion
823
*/
824
setMyLocationEnabled(enabled: boolean): Promise<any>;
825
826
/**
827
* Remove the map
828
*/
829
remove(): void;
830
831
/**
832
* Clear all overlays from map
833
*/
834
clear(): void;
835
836
/**
837
* Add event listener
838
* @param event Event name
839
* @returns Observable emitting map events
840
*/
841
on(event: string): Observable<any>;
842
}
843
844
/**
845
* Camera position for map view
846
*/
847
interface CameraPosition {
848
/** Target coordinates */
849
target?: { lat: number; lng: number; };
850
/** Zoom level */
851
zoom?: number;
852
/** Tilt angle */
853
tilt?: number;
854
/** Bearing angle */
855
bearing?: number;
856
/** Animation duration */
857
duration?: number;
858
}
859
860
/**
861
* Marker configuration options
862
*/
863
interface MarkerOptions {
864
/** Marker position */
865
position: { lat: number; lng: number; };
866
/** Marker title */
867
title?: string;
868
/** Marker snippet (subtitle) */
869
snippet?: string;
870
/** Marker icon */
871
icon?: string | any;
872
/** Marker anchor point */
873
anchor?: { x: number; y: number; };
874
/** Whether marker is draggable */
875
draggable?: boolean;
876
/** Whether marker is visible */
877
visible?: boolean;
878
/** Marker z-index */
879
zIndex?: number;
880
/** Custom data */
881
data?: any;
882
}
883
884
/**
885
* GoogleMap class for map integration
886
*/
887
class GoogleMap {
888
/**
889
* Check if Google Maps is available
890
* @returns Promise resolving to availability status
891
*/
892
static isAvailable(): Promise<boolean>;
893
894
/**
895
* Create Google Map instance
896
* @param element HTML element or selector for map container
897
* @param options Map configuration options
898
* @returns GoogleMapObject instance
899
*/
900
static create(element: string | HTMLElement, options?: GoogleMapOptions): GoogleMapObject;
901
}
902
```
903
904
**Usage Examples:**
905
906
```typescript
907
import { GoogleMap, GoogleMapOptions } from 'ionic-native';
908
909
// Initialize map
910
async function initializeMap(elementId: string) {
911
try {
912
const isAvailable = await GoogleMap.isAvailable();
913
if (!isAvailable) {
914
console.error('Google Maps not available');
915
return;
916
}
917
918
const options: GoogleMapOptions = {
919
center: { lat: 37.7749, lng: -122.4194 },
920
zoom: 12,
921
mapType: 'MAP_TYPE_NORMAL',
922
myLocationEnabled: true,
923
myLocationButtonEnabled: true,
924
compassEnabled: true,
925
zoomControlsEnabled: false,
926
scrollGesturesEnabled: true,
927
zoomGesturesEnabled: true,
928
rotateGesturesEnabled: true,
929
tiltGesturesEnabled: true
930
};
931
932
const map = GoogleMap.create(elementId, options);
933
934
// Set up event listeners
935
map.on('MAP_READY').subscribe(() => {
936
console.log('Map is ready');
937
addMapFeatures(map);
938
});
939
940
map.on('MAP_CLICK').subscribe((event) => {
941
console.log('Map clicked at:', event.latLng);
942
});
943
944
return map;
945
} catch (error) {
946
console.error('Map initialization failed:', error);
947
}
948
}
949
950
// Add markers and features to map
951
async function addMapFeatures(map: GoogleMapObject) {
952
// Add custom markers
953
const locations = [
954
{ lat: 37.7749, lng: -122.4194, title: 'San Francisco', snippet: 'The Golden City' },
955
{ lat: 37.7849, lng: -122.4094, title: 'North Beach', snippet: 'Italian District' },
956
{ lat: 37.7649, lng: -122.4294, title: 'Mission District', snippet: 'Vibrant Neighborhood' }
957
];
958
959
for (const location of locations) {
960
await map.addMarker({
961
position: { lat: location.lat, lng: location.lng },
962
title: location.title,
963
snippet: location.snippet,
964
icon: 'blue',
965
draggable: false,
966
data: { type: 'poi', id: location.title.toLowerCase() }
967
});
968
}
969
970
// Add marker click listener
971
map.on('MARKER_CLICK').subscribe((marker) => {
972
console.log('Marker clicked:', marker.title);
973
showMarkerDetails(marker);
974
});
975
}
976
977
// Location-based map features
978
class LocationMap {
979
private map: GoogleMapObject;
980
private userMarker: any;
981
private locationWatcher: any;
982
983
async initialize(elementId: string) {
984
this.map = GoogleMap.create(elementId, {
985
myLocationEnabled: true,
986
myLocationButtonEnabled: true,
987
zoom: 15
988
});
989
990
await this.map.on('MAP_READY').toPromise();
991
this.startLocationTracking();
992
}
993
994
async startLocationTracking() {
995
try {
996
const position = await Geolocation.getCurrentPosition({
997
enableHighAccuracy: true
998
});
999
1000
// Center map on user location
1001
this.map.animateCamera({
1002
target: {
1003
lat: position.coords.latitude,
1004
lng: position.coords.longitude
1005
},
1006
zoom: 16,
1007
duration: 1000
1008
});
1009
1010
// Add user marker
1011
this.userMarker = await this.map.addMarker({
1012
position: {
1013
lat: position.coords.latitude,
1014
lng: position.coords.longitude
1015
},
1016
title: 'You are here',
1017
icon: 'red'
1018
});
1019
1020
// Watch position changes
1021
this.locationWatcher = Geolocation.watchPosition({
1022
enableHighAccuracy: true,
1023
timeout: 10000,
1024
maximumAge: 1000
1025
}).subscribe((pos) => {
1026
this.updateUserPosition(pos.coords.latitude, pos.coords.longitude);
1027
});
1028
1029
} catch (error) {
1030
console.error('Location tracking failed:', error);
1031
}
1032
}
1033
1034
private async updateUserPosition(lat: number, lng: number) {
1035
if (this.userMarker) {
1036
// Update marker position
1037
this.userMarker.setPosition({ lat, lng });
1038
1039
// Optionally animate camera to follow user
1040
this.map.animateCamera({
1041
target: { lat, lng },
1042
duration: 500
1043
});
1044
}
1045
}
1046
1047
async addNearbyPlaces(places: any[]) {
1048
for (const place of places) {
1049
await this.map.addMarker({
1050
position: { lat: place.lat, lng: place.lng },
1051
title: place.name,
1052
snippet: place.description,
1053
icon: this.getPlaceIcon(place.type),
1054
data: place
1055
});
1056
}
1057
}
1058
1059
private getPlaceIcon(type: string): string {
1060
const iconMap: { [key: string]: string } = {
1061
restaurant: 'orange',
1062
gas_station: 'green',
1063
hospital: 'red',
1064
school: 'blue',
1065
park: 'green'
1066
};
1067
1068
return iconMap[type] || 'gray';
1069
}
1070
1071
destroy() {
1072
if (this.locationWatcher) {
1073
this.locationWatcher.unsubscribe();
1074
}
1075
1076
if (this.map) {
1077
this.map.remove();
1078
}
1079
}
1080
}
1081
```