-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Copy pathMapView.tsx
97 lines (86 loc) · 3.7 KB
/
MapView.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import {View} from 'react-native';
import {useFocusEffect} from '@react-navigation/native';
import Mapbox, {MapState, MarkerView, setAccessToken} from '@rnmapbox/maps';
import {forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
import responder from './responder';
import utils from './utils';
import Direction from './Direction';
import CONST from '../../CONST';
import {MapViewProps, MapViewHandle} from './MapViewTypes';
const MapView = forwardRef<MapViewHandle, MapViewProps>(({accessToken, style, mapPadding, styleURL, pitchEnabled, initialState, waypoints, directionCoordinates}, ref) => {
const cameraRef = useRef<Mapbox.Camera>(null);
const [isIdle, setIsIdle] = useState(false);
useImperativeHandle(
ref,
() => ({
flyTo: (location: [number, number], zoomLevel: number = CONST.MAPBOX.DEFAULT_ZOOM, animationDuration?: number) =>
cameraRef.current?.setCamera({zoomLevel, centerCoordinate: location, animationDuration}),
fitBounds: (northEast: [number, number], southWest: [number, number], paddingConfig?: number | number[] | undefined, animationDuration?: number | undefined) =>
cameraRef.current?.fitBounds(northEast, southWest, paddingConfig, animationDuration),
}),
[],
);
// When the page loses focus, we temporarily set the "idled" state to false.
// When the page regains focus, the onIdled method of the map will set the actual "idled" state,
// which in turn triggers the callback.
useFocusEffect(
useCallback(() => {
if (waypoints?.length && isIdle) {
if (waypoints.length === 1) {
cameraRef.current?.setCamera({
zoomLevel: 15,
animationDuration: 1500,
centerCoordinate: waypoints[0].coordinate,
});
} else {
const {southWest, northEast} = utils.getBounds(waypoints.map((waypoint) => waypoint.coordinate));
cameraRef.current?.fitBounds(northEast, southWest, mapPadding, 1000);
}
}
return () => {
setIsIdle(false);
};
}, [mapPadding, waypoints, isIdle]),
);
useEffect(() => {
setAccessToken(accessToken);
}, [accessToken]);
const setMapIdle = (e: MapState) => {
if (e.gestures.isGestureActive) return;
setIsIdle(true);
};
return (
<View style={style}>
<Mapbox.MapView
style={{flex: 1}}
styleURL={styleURL}
onMapIdle={setMapIdle}
pitchEnabled={pitchEnabled}
// eslint-disable-next-line
{...responder.panHandlers}
>
<Mapbox.Camera
ref={cameraRef}
defaultSettings={{
centerCoordinate: initialState?.location,
zoomLevel: initialState?.zoom,
}}
/>
{waypoints?.map(({coordinate, markerComponent, id}) => {
const MarkerComponent = markerComponent;
return (
<MarkerView
id={id}
key={id}
coordinate={coordinate}
>
<MarkerComponent />
</MarkerView>
);
})}
{directionCoordinates && <Direction coordinates={directionCoordinates} />}
</Mapbox.MapView>
</View>
);
});
export default memo(MapView);