-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathdirections-service.ts
138 lines (122 loc) · 3.86 KB
/
directions-service.ts
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import {useContext, useMemo, useEffect, useCallback} from 'react';
import {GoogleMapsContext} from '../google-maps-provider';
export interface DirectionsServiceProps {
renderOnMap?: boolean;
renderOptions?: google.maps.DirectionsRendererOptions;
}
interface DirectionsServiceHookReturns {
directionsService: google.maps.DirectionsService | null;
directionsRenderer: google.maps.DirectionsRenderer | null;
findRoute:
| ((
request: google.maps.DirectionsRequest
) => Promise<google.maps.DirectionsResult>)
| null;
findAndRenderRoute:
| ((
request: google.maps.DirectionsRequest
) => Promise<google.maps.DirectionsResult>)
| null;
renderRouteOfIndex: (index: number) => void;
}
/**
* Hook to get Google Maps Places Directions Service instance
*/
export const useDirectionsService = (
props: DirectionsServiceProps = {}
): DirectionsServiceHookReturns => {
const {renderOnMap, renderOptions} = props;
const {googleMapsAPIIsLoaded, map} = useContext(GoogleMapsContext);
// Creates a Directions Service instance
const directionsService =
useMemo<google.maps.DirectionsService | null>(() => {
// Wait for Google Maps API to be loaded
if (!googleMapsAPIIsLoaded) {
return null;
}
return new google.maps.DirectionsService();
}, [googleMapsAPIIsLoaded]);
// Creates a Directions Renderer instance
const directionsRenderer =
useMemo<google.maps.DirectionsRenderer | null>(() => {
// Wait for map to be initialized
if (!map || !renderOnMap) {
return null;
}
const renderer = new google.maps.DirectionsRenderer(renderOptions);
renderer.setMap(map);
return renderer;
}, [map, renderOnMap]);
// Updates the directions renderer options
useEffect(() => {
if (!directionsRenderer) {
return;
}
directionsRenderer.setOptions(renderOptions || {});
}, [renderOptions]);
// Custom Directions route request
const findRoute = useCallback(
(
request: google.maps.DirectionsRequest
): Promise<google.maps.DirectionsResult> =>
new Promise((resolve, reject) => {
if (directionsService) {
directionsService.route(
request,
(
result: google.maps.DirectionsResult | null,
status: google.maps.DirectionsStatus
): void => {
if (status !== google.maps.DirectionsStatus.OK || !result) {
reject(status);
} else {
resolve(result);
}
}
);
}
}),
[directionsService]
);
// Custom Directions route request followed by directions rendering
const findAndRenderRoute = useCallback(
(
request: google.maps.DirectionsRequest
): Promise<google.maps.DirectionsResult> =>
new Promise((resolve, reject) => {
if (directionsService) {
directionsService.route(
request,
(
result: google.maps.DirectionsResult | null,
status: google.maps.DirectionsStatus
): void => {
if (status !== google.maps.DirectionsStatus.OK || !result) {
reject(status);
} else {
if (directionsRenderer) {
directionsRenderer.setDirections(result);
}
resolve(result);
}
}
);
}
}),
[directionsService, directionsRenderer]
);
// Renders directions route of given index
const renderRouteOfIndex = (index: number) => {
if (directionsRenderer) {
directionsRenderer.setRouteIndex(index);
}
};
return {
directionsService,
directionsRenderer,
findRoute: directionsService && findRoute,
findAndRenderRoute:
directionsService && directionsRenderer && findAndRenderRoute,
renderRouteOfIndex
};
};