expo-gaode-map 2.0.0-alpha.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,651 +0,0 @@
1
- # Usage Examples
2
-
3
- English | [简体中文](./EXAMPLES.md)
4
-
5
- Complete usage examples and best practices.
6
-
7
- > 📖 **Recommended Reading**: [Initialization Guide](./INITIALIZATION.en.md) - Detailed initialization process and permission handling
8
-
9
- ## Table of Contents
10
-
11
- - [Complete Application Example](#complete-application-example)
12
- - [Basic Map Application](#basic-map-application)
13
- - [Location Tracking Application](#location-tracking-application)
14
- - [Overlay Examples](#overlay-examples)
15
- - [Advanced Usage](#advanced-usage)
16
-
17
- ## Complete Application Example
18
-
19
- Complete example with permission management, error handling, and loading states:
20
-
21
- ```tsx
22
- import { useEffect, useState } from 'react';
23
- import { View, Text, Alert, Linking, Platform } from 'react-native';
24
- import {
25
- MapView,
26
- initSDK,
27
- checkLocationPermission,
28
- requestLocationPermission,
29
- getCurrentLocation,
30
- type LatLng,
31
- } from 'expo-gaode-map';
32
-
33
- export default function App() {
34
- const [initialPosition, setInitialPosition] = useState<{
35
- target: LatLng;
36
- zoom: number;
37
- } | null>(null);
38
- const [error, setError] = useState<string | null>(null);
39
-
40
- useEffect(() => {
41
- const initialize = async () => {
42
- try {
43
- // 1. Initialize SDK
44
- initSDK({
45
- androidKey: 'your-android-api-key',
46
- iosKey: 'your-ios-api-key',
47
- });
48
-
49
- // 2. Check permission
50
- const status = await checkLocationPermission();
51
-
52
- // 3. Request permission if needed
53
- if (!status.granted) {
54
- const result = await requestLocationPermission();
55
-
56
- if (!result.granted) {
57
- // Permission denied
58
- setInitialPosition({
59
- target: { latitude: 39.9, longitude: 116.4 },
60
- zoom: 10
61
- });
62
-
63
- // Guide user to settings
64
- if (!result.canAskAgain) {
65
- Alert.alert(
66
- 'Location Permission Required',
67
- 'Please enable location permission in settings',
68
- [
69
- { text: 'Cancel' },
70
- { text: 'Settings', onPress: () => {
71
- if (Platform.OS === 'ios') {
72
- Linking.openURL('app-settings:');
73
- } else {
74
- Linking.openSettings();
75
- }
76
- }}
77
- ]
78
- );
79
- }
80
- return;
81
- }
82
- }
83
-
84
- // 4. Get location
85
- const location = await getCurrentLocation();
86
- setInitialPosition({
87
- target: {
88
- latitude: location.latitude,
89
- longitude: location.longitude
90
- },
91
- zoom: 15
92
- });
93
-
94
- } catch (err) {
95
- console.error('Initialization failed:', err);
96
- setError('Initialization failed');
97
- setInitialPosition({
98
- target: { latitude: 39.9, longitude: 116.4 },
99
- zoom: 10
100
- });
101
- }
102
- };
103
-
104
- initialize();
105
- }, []);
106
-
107
- // Loading state
108
- if (!initialPosition && !error) {
109
- return (
110
- <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
111
- <Text>Loading map...</Text>
112
- </View>
113
- );
114
- }
115
-
116
- // Error state
117
- if (error) {
118
- return (
119
- <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
120
- <Text>{error}</Text>
121
- </View>
122
- );
123
- }
124
-
125
- return (
126
- <MapView
127
- style={{ flex: 1 }}
128
- initialCameraPosition={initialPosition!}
129
- myLocationEnabled={true}
130
- onLoad={() => console.log('Map loaded')}
131
- />
132
- );
133
- }
134
- ```
135
-
136
- ## Basic Map Application
137
-
138
- ```tsx
139
- import React, { useRef, useEffect } from 'react';
140
- import { View, StyleSheet, Button } from 'react-native';
141
- import {
142
- MapView,
143
- initSDK,
144
- Circle,
145
- Marker,
146
- Polyline,
147
- Polygon,
148
- type MapViewRef
149
- } from 'expo-gaode-map';
150
-
151
- export default function App() {
152
- const mapRef = useRef<MapViewRef>(null);
153
-
154
- useEffect(() => {
155
- const initialize = async () => {
156
- initSDK({
157
- androidKey: 'your-android-api-key',
158
- iosKey: 'your-ios-api-key',
159
- });
160
-
161
- // Check and request permission
162
- const status = await checkLocationPermission();
163
- if (!status.granted) {
164
- await requestLocationPermission();
165
- }
166
- };
167
-
168
- initialize();
169
- }, []);
170
-
171
- const handleMoveCamera = async () => {
172
- await mapRef.current?.moveCamera(
173
- {
174
- target: { latitude: 40.0, longitude: 116.5 },
175
- zoom: 15,
176
- },
177
- 1000
178
- );
179
- };
180
-
181
- return (
182
- <View style={styles.container}>
183
- <MapView
184
- ref={mapRef}
185
- style={styles.map}
186
- initialCameraPosition={{
187
- target: { latitude: 39.9, longitude: 116.4 },
188
- zoom: 10,
189
- }}
190
- myLocationEnabled={true}
191
- followUserLocation={false}
192
- trafficEnabled={true}
193
- onMapPress={(e) => console.log('Map pressed', e.nativeEvent)}
194
- onLoad={() => console.log('Map loaded')}
195
- >
196
- {/* Circle overlay */}
197
- <Circle
198
- center={{ latitude: 39.9, longitude: 116.4 }}
199
- radius={1000}
200
- fillColor="#8800FF00"
201
- strokeColor="#FFFF0000"
202
- strokeWidth={2}
203
- />
204
-
205
- {/* Marker */}
206
- <Marker
207
- position={{ latitude: 39.95, longitude: 116.45 }}
208
- title="This is a marker"
209
- draggable={true}
210
- />
211
-
212
- {/* Polyline */}
213
- <Polyline
214
- points={[
215
- { latitude: 39.9, longitude: 116.4 },
216
- { latitude: 39.95, longitude: 116.45 },
217
- { latitude: 40.0, longitude: 116.5 },
218
- ]}
219
- width={5}
220
- color="#FF0000FF"
221
- />
222
-
223
- {/* Polygon */}
224
- <Polygon
225
- points={[
226
- { latitude: 39.85, longitude: 116.35 },
227
- { latitude: 39.85, longitude: 116.45 },
228
- { latitude: 39.75, longitude: 116.40 },
229
- ]}
230
- fillColor="#880000FF"
231
- strokeColor="#FFFF0000"
232
- strokeWidth={2}
233
- />
234
- </MapView>
235
-
236
- <View style={styles.controls}>
237
- <Button title="Move Camera" onPress={handleMoveCamera} />
238
- </View>
239
- </View>
240
- );
241
- }
242
-
243
- const styles = StyleSheet.create({
244
- container: {
245
- flex: 1,
246
- },
247
- map: {
248
- flex: 1,
249
- },
250
- controls: {
251
- position: 'absolute',
252
- bottom: 20,
253
- left: 20,
254
- right: 20,
255
- },
256
- });
257
- ```
258
-
259
- ## Location Tracking Application
260
-
261
- ```tsx
262
- import React, { useEffect, useState } from 'react';
263
- import { View, Text, Button, StyleSheet } from 'react-native';
264
- import {
265
- MapView,
266
- initSDK,
267
- configure,
268
- start,
269
- stop,
270
- getCurrentLocation,
271
- addLocationListener,
272
- type Location,
273
- } from 'expo-gaode-map';
274
-
275
- export default function LocationApp() {
276
- const [location, setLocation] = useState<Location | null>(null);
277
- const [isTracking, setIsTracking] = useState(false);
278
-
279
- useEffect(() => {
280
- const initialize = async () => {
281
- // Initialize SDK
282
- initSDK({
283
- androidKey: 'your-android-api-key',
284
- iosKey: 'your-ios-api-key',
285
- });
286
-
287
- // Check and request permission
288
- const status = await checkLocationPermission();
289
- if (!status.granted) {
290
- await requestLocationPermission();
291
- }
292
-
293
- // Configure location parameters
294
- configure({
295
- withReGeocode: true,
296
- mode: 0,
297
- interval: 2000,
298
- });
299
-
300
- // Listen to location updates
301
- const subscription = addLocationListener((loc) => {
302
- console.log('Location update:', loc);
303
- setLocation(loc);
304
- });
305
-
306
- return () => subscription.remove();
307
- };
308
-
309
- initialize();
310
- }, []);
311
-
312
- const handleStartTracking = () => {
313
- start();
314
- setIsTracking(true);
315
- };
316
-
317
- const handleStopTracking = () => {
318
- stop();
319
- setIsTracking(false);
320
- };
321
-
322
- const handleGetLocation = async () => {
323
- try {
324
- const loc = await getCurrentLocation();
325
- setLocation(loc);
326
- } catch (error) {
327
- console.error('Get location failed:', error);
328
- }
329
- };
330
-
331
- return (
332
- <View style={styles.container}>
333
- <MapView
334
- style={styles.map}
335
- myLocationEnabled={true}
336
- followUserLocation={isTracking}
337
- initialCameraPosition={{
338
- target: {
339
- latitude: location?.latitude || 39.9,
340
- longitude: location?.longitude || 116.4
341
- },
342
- zoom: 15,
343
- }}
344
- />
345
-
346
- {location && (
347
- <View style={styles.info}>
348
- <Text style={styles.infoText}>
349
- Latitude: {location.latitude.toFixed(6)}
350
- </Text>
351
- <Text style={styles.infoText}>
352
- Longitude: {location.longitude.toFixed(6)}
353
- </Text>
354
- <Text style={styles.infoText}>
355
- Accuracy: {location.accuracy.toFixed(2)} m
356
- </Text>
357
- {location.address && (
358
- <Text style={styles.infoText}>
359
- Address: {location.address}
360
- </Text>
361
- )}
362
- </View>
363
- )}
364
-
365
- <View style={styles.controls}>
366
- <Button
367
- title="Get Location"
368
- onPress={handleGetLocation}
369
- />
370
- <View style={{ height: 10 }} />
371
- <Button
372
- title={isTracking ? 'Stop Tracking' : 'Start Tracking'}
373
- onPress={isTracking ? handleStopTracking : handleStartTracking}
374
- color={isTracking ? '#FF3B30' : '#007AFF'}
375
- />
376
- </View>
377
- </View>
378
- );
379
- }
380
-
381
- const styles = StyleSheet.create({
382
- container: {
383
- flex: 1,
384
- },
385
- map: {
386
- flex: 1,
387
- },
388
- info: {
389
- position: 'absolute',
390
- top: 50,
391
- left: 20,
392
- right: 20,
393
- backgroundColor: 'white',
394
- padding: 15,
395
- borderRadius: 10,
396
- shadowColor: '#000',
397
- shadowOffset: { width: 0, height: 2 },
398
- shadowOpacity: 0.25,
399
- shadowRadius: 3.84,
400
- elevation: 5,
401
- },
402
- infoText: {
403
- fontSize: 14,
404
- marginBottom: 5,
405
- color: '#333',
406
- },
407
- controls: {
408
- position: 'absolute',
409
- bottom: 30,
410
- left: 20,
411
- right: 20,
412
- },
413
- });
414
- ```
415
-
416
- ## Overlay Examples
417
-
418
- ### Circle
419
-
420
- **Declarative usage:**
421
- ```tsx
422
- <MapView style={{ flex: 1 }}>
423
- <Circle
424
- center={{ latitude: 39.9, longitude: 116.4 }}
425
- radius={1000}
426
- fillColor="#8800FF00"
427
- strokeColor="#FFFF0000"
428
- strokeWidth={2}
429
- onPress={(e) => console.log('Circle pressed')}
430
- />
431
- </MapView>
432
- ```
433
-
434
-
435
- ### Marker
436
-
437
- **Declarative usage - Basic marker:**
438
- ```tsx
439
- <MapView style={{ flex: 1 }}>
440
- <Marker
441
- position={{ latitude: 39.9, longitude: 116.4 }}
442
- title="Title"
443
- snippet="Description"
444
- draggable={true}
445
- onPress={(e) => console.log('Marker pressed')}
446
- onDragEnd={(e) => console.log('Drag ended', e.nativeEvent)}
447
- />
448
- </MapView>
449
- ```
450
-
451
- **Declarative usage - Custom icon:**
452
- ```tsx
453
- import { Image } from 'react-native';
454
-
455
- const iconUri = Image.resolveAssetSource(require('./assets/marker-icon.png')).uri;
456
-
457
- <MapView style={{ flex: 1 }}>
458
- <Marker
459
- position={{ latitude: 39.9, longitude: 116.4 }}
460
- title="Custom Icon"
461
- icon={iconUri}
462
- iconWidth={50}
463
- iconHeight={50}
464
- onPress={(e) => console.log('Custom icon marker pressed')}
465
- />
466
- </MapView>
467
- ```
468
-
469
- **Declarative usage - Custom view:**
470
- ```tsx
471
- import { View, Text, StyleSheet } from 'react-native';
472
-
473
- <MapView style={{ flex: 1 }}>
474
- <Marker
475
- position={{ latitude: 39.9, longitude: 116.4 }}
476
- customViewWidth={120}
477
- customViewHeight={40}
478
- onPress={(e) => console.log('Custom view marker pressed')}
479
- >
480
- <View style={styles.markerContainer}>
481
- <Text style={styles.markerText}>Custom Content</Text>
482
- </View>
483
- </Marker>
484
- </MapView>
485
-
486
- const styles = StyleSheet.create({
487
- markerContainer: {
488
- backgroundColor: '#fff',
489
- padding: 8,
490
- borderRadius: 8,
491
- borderWidth: 2,
492
- borderColor: '#007AFF',
493
- },
494
- markerText: {
495
- color: '#007AFF',
496
- fontWeight: 'bold',
497
- fontSize: 14,
498
- },
499
- });
500
- ```
501
-
502
- > **Important Notes**:
503
- > - **Custom Icon**: Use `icon` property with `iconWidth` and `iconHeight` to control icon size
504
- > - **Custom View**: Use `children` with `customViewWidth` and `customViewHeight` to control custom view size
505
- > - `iconWidth/iconHeight` only apply to `icon` property, not `children`
506
- > - `customViewWidth/customViewHeight` only apply to `children` property, not `icon`
507
-
508
- **Imperative usage:**
509
- ```tsx
510
- await mapRef.current?.addMarker('marker1', {
511
- position: { latitude: 39.9, longitude: 116.4 },
512
- title: 'Title',
513
- snippet: 'Description',
514
- draggable: true,
515
- });
516
-
517
- await mapRef.current?.updateMarker('marker1', {
518
- position: { latitude: 40.0, longitude: 116.5 },
519
- });
520
-
521
- await mapRef.current?.removeMarker('marker1');
522
- ```
523
-
524
- > **⚠️ Limitation**: Markers added via imperative API **do not support event callbacks** (onPress, onDragEnd, etc.). Use declarative `<Marker>` component for event handling.
525
-
526
- ### Polyline
527
-
528
- **Declarative usage - Normal polyline:**
529
- ```tsx
530
- <MapView style={{ flex: 1 }}>
531
- <Polyline
532
- points={[
533
- { latitude: 39.9, longitude: 116.4 },
534
- { latitude: 39.95, longitude: 116.45 },
535
- { latitude: 40.0, longitude: 116.5 },
536
- ]}
537
- width={5}
538
- color="#FFFF0000"
539
- onPress={(e) => console.log('Polyline pressed')}
540
- />
541
- </MapView>
542
- ```
543
-
544
- **Declarative usage - Textured polyline:**
545
- ```tsx
546
- import { Image } from 'react-native';
547
-
548
- const iconUri = Image.resolveAssetSource(require('./assets/arrow.png')).uri;
549
-
550
- <MapView style={{ flex: 1 }}>
551
- <Polyline
552
- points={[
553
- { latitude: 39.9, longitude: 116.4 },
554
- { latitude: 39.95, longitude: 116.45 },
555
- { latitude: 40.0, longitude: 116.5 },
556
- ]}
557
- width={20}
558
- color="#FFFF0000"
559
- texture={iconUri}
560
- onPress={(e) => console.log('Textured polyline pressed')}
561
- />
562
- </MapView>
563
- ```
564
-
565
- > **Note**:
566
- > - Color format uses ARGB (`#AARRGGBB`), e.g., `#FFFF0000` for opaque red
567
- > - `texture` supports network images (http/https) and local files (file://)
568
- > - Texture tiles along the polyline direction
569
- > - Recommend larger `width` values (e.g., 20) for better texture display
570
- > - **Segment Texture Limitation**: Single Polyline can only have one texture. For different textures on segments, create multiple Polyline components
571
-
572
- ### Polygon
573
-
574
- **Declarative usage:**
575
- ```tsx
576
- <MapView style={{ flex: 1 }}>
577
- <Polygon
578
- points={[
579
- { latitude: 39.9, longitude: 116.3 },
580
- { latitude: 39.9, longitude: 116.4 },
581
- { latitude: 39.8, longitude: 116.4 },
582
- ]}
583
- fillColor="#8800FF00"
584
- strokeColor="#FFFF0000"
585
- strokeWidth={2}
586
- onPress={(e) => console.log('Polygon pressed')}
587
- />
588
- </MapView>
589
- ```
590
-
591
- **Imperative usage:**
592
- ```tsx
593
- await mapRef.current?.addPolygon('polygon1', {
594
- points: [
595
- { latitude: 39.9, longitude: 116.3 },
596
- { latitude: 39.9, longitude: 116.4 },
597
- { latitude: 39.8, longitude: 116.4 },
598
- ],
599
- fillColor: 0x8800FF00,
600
- strokeColor: 0xFFFF0000,
601
- strokeWidth: 2,
602
- });
603
- ```
604
-
605
- ## Advanced Usage
606
-
607
- ### Custom Location Blue Dot
608
-
609
- ```tsx
610
- import { Image } from 'react-native';
611
-
612
- const iconUri = Image.resolveAssetSource(require('./assets/location-icon.png')).uri;
613
-
614
- <MapView
615
- myLocationEnabled={true}
616
- userLocationRepresentation={{
617
- showsAccuracyRing: true,
618
- fillColor: '#4285F4',
619
- strokeColor: '#1967D2',
620
- lineWidth: 2,
621
- image: iconUri,
622
- imageWidth: 40,
623
- imageHeight: 40,
624
- }}
625
- />
626
- ```
627
-
628
-
629
- ### Zoom Level Limits
630
-
631
- ```tsx
632
- <MapView
633
- maxZoom={18}
634
- minZoom={5}
635
- initialCameraPosition={{
636
- target: { latitude: 39.9, longitude: 116.4 },
637
- zoom: 10,
638
- }}
639
- />
640
- ```
641
-
642
- ### Heading Updates (iOS)
643
-
644
- ```tsx
645
- import { startUpdatingHeading, stopUpdatingHeading } from 'expo-gaode-map';
646
-
647
- // Start heading updates
648
- startUpdatingHeading();
649
-
650
- // Stop heading updates
651
- stopUpdatingHeading();