0
# Advanced Components
1
2
Specialized components for custom overlays, directions, Street View, and advanced Google Maps features that provide enhanced functionality beyond basic mapping.
3
4
## Capabilities
5
6
### OverlayView
7
8
Component for creating custom overlays that render React elements at specific geographic positions on the map.
9
10
```javascript { .api }
11
/**
12
* Custom overlay component for rendering React elements on the map
13
*/
14
class OverlayView extends Component<OverlayViewProps> {
15
/** Predefined map pane constants */
16
static FLOAT_PANE: string;
17
static MAP_PANE: string;
18
static MARKER_LAYER: string;
19
static OVERLAY_LAYER: string;
20
static OVERLAY_MOUSE_TARGET: string;
21
22
/** Returns the map panes for positioning */
23
getPanes(): google.maps.MapPanes;
24
/** Returns the map projection for coordinate conversion */
25
getProjection(): google.maps.MapCanvasProjection;
26
}
27
28
interface OverlayViewProps {
29
/** Geographic bounds for the overlay (alternative to position) */
30
bounds?: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral;
31
/** React children to render in the overlay */
32
children?: ReactNode;
33
/** Function to adjust pixel positioning */
34
getPixelPositionOffset?: (width: number, height: number) => { x?: number, y?: number };
35
/** Map pane to render the overlay in */
36
mapPaneName?: string;
37
/** Geographic position for the overlay */
38
position?: google.maps.LatLng | google.maps.LatLngLiteral;
39
}
40
```
41
42
**Usage Example:**
43
44
```javascript
45
import { OverlayView } from "react-google-maps";
46
47
const CustomOverlay = ({ position, children }) => (
48
<OverlayView
49
position={position}
50
mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
51
getPixelPositionOffset={(width, height) => ({
52
x: -(width / 2),
53
y: -(height / 2),
54
})}
55
>
56
<div style={{
57
background: "white",
58
border: "1px solid #ccc",
59
padding: "10px",
60
borderRadius: "4px",
61
boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
62
}}>
63
{children}
64
</div>
65
</OverlayView>
66
);
67
68
// Usage
69
<GoogleMap defaultZoom={10} defaultCenter={{ lat: 37.7749, lng: -122.4194 }}>
70
<CustomOverlay position={{ lat: 37.7749, lng: -122.4194 }}>
71
<h3>Custom Overlay</h3>
72
<p>This is a React component rendered on the map!</p>
73
<button onClick={() => alert("Clicked!")}>Click me</button>
74
</CustomOverlay>
75
</GoogleMap>
76
```
77
78
### DirectionsRenderer
79
80
Component for displaying directions and routes on the map with support for waypoints and custom styling.
81
82
```javascript { .api }
83
/**
84
* Directions renderer component for displaying routes
85
*/
86
class DirectionsRenderer extends Component<DirectionsRendererProps> {
87
/** Returns the current directions result */
88
getDirections(): google.maps.DirectionsResult;
89
/** Returns the panel element for text directions */
90
getPanel(): Node;
91
/** Returns the current route index */
92
getRouteIndex(): number;
93
}
94
95
interface DirectionsRendererProps {
96
// Default props
97
defaultDirections?: google.maps.DirectionsResult;
98
defaultOptions?: google.maps.DirectionsRendererOptions;
99
defaultPanel?: Node;
100
defaultRouteIndex?: number;
101
102
// Controlled props
103
directions?: google.maps.DirectionsResult;
104
options?: google.maps.DirectionsRendererOptions;
105
panel?: Node;
106
routeIndex?: number;
107
108
// Event handlers
109
onDirectionsChanged?(): void;
110
}
111
```
112
113
**Usage Example:**
114
115
```javascript
116
import { DirectionsRenderer } from "react-google-maps";
117
118
const DirectionsMap = () => {
119
const [directions, setDirections] = useState(null);
120
const [directionsService] = useState(new google.maps.DirectionsService());
121
122
useEffect(() => {
123
directionsService.route(
124
{
125
origin: { lat: 37.7749, lng: -122.4194 }, // San Francisco
126
destination: { lat: 37.4419, lng: -122.1430 }, // Palo Alto
127
travelMode: google.maps.TravelMode.DRIVING,
128
waypoints: [
129
{ location: { lat: 37.6879, lng: -122.4074 }, stopover: true } // SFO
130
],
131
optimizeWaypoints: true
132
},
133
(result, status) => {
134
if (status === google.maps.DirectionsStatus.OK) {
135
setDirections(result);
136
}
137
}
138
);
139
}, [directionsService]);
140
141
return (
142
<GoogleMap defaultZoom={10} defaultCenter={{ lat: 37.6, lng: -122.3 }}>
143
{directions && (
144
<DirectionsRenderer
145
directions={directions}
146
options={{
147
suppressMarkers: false,
148
suppressInfoWindows: false,
149
polylineOptions: {
150
strokeColor: "#ff0000",
151
strokeWeight: 4
152
}
153
}}
154
onDirectionsChanged={() => {
155
console.log("Directions changed");
156
}}
157
/>
158
)}
159
</GoogleMap>
160
);
161
};
162
```
163
164
### StreetViewPanorama
165
166
Component for displaying Google Street View panoramas either as standalone components or integrated with maps.
167
168
```javascript { .api }
169
/**
170
* Street View panorama component
171
*/
172
class StreetViewPanorama extends Component<StreetViewPanoramaProps> {
173
/** Returns the panorama's navigation links */
174
getLinks(): google.maps.StreetViewLink[];
175
/** Returns the panorama's location information */
176
getLocation(): google.maps.StreetViewLocation;
177
/** Returns whether motion tracking is enabled */
178
getMotionTracking(): boolean;
179
/** Returns the panorama ID */
180
getPano(): string;
181
/** Returns the photographer's point of view */
182
getPhotographerPov(): google.maps.StreetViewPov;
183
/** Returns the panorama's position */
184
getPosition(): google.maps.LatLng;
185
/** Returns the current point of view */
186
getPov(): google.maps.StreetViewPov;
187
/** Returns the panorama's status */
188
getStatus(): google.maps.StreetViewStatus;
189
/** Returns whether the panorama is visible */
190
getVisible(): boolean;
191
/** Returns the current zoom level */
192
getZoom(): number;
193
}
194
195
interface StreetViewPanoramaProps {
196
// Default props
197
defaultLinks?: google.maps.StreetViewLink[];
198
defaultMotionTracking?: boolean;
199
defaultOptions?: google.maps.StreetViewPanoramaOptions;
200
defaultPano?: string;
201
defaultPosition?: google.maps.LatLng | google.maps.LatLngLiteral;
202
defaultPov?: google.maps.StreetViewPov;
203
defaultVisible?: boolean;
204
defaultZoom?: number;
205
206
// Controlled props
207
links?: google.maps.StreetViewLink[];
208
motionTracking?: boolean;
209
options?: google.maps.StreetViewPanoramaOptions;
210
pano?: string;
211
position?: google.maps.LatLng | google.maps.LatLngLiteral;
212
pov?: google.maps.StreetViewPov;
213
visible?: boolean;
214
zoom?: number;
215
216
// Event handlers
217
onCloseClick?(e: Event): void;
218
onPanoChanged?(): void;
219
onPositionChanged?(): void;
220
onPovChanged?(): void;
221
onResize?(): void;
222
onStatusChanged?(): void;
223
onVisibleChanged?(): void;
224
onZoomChanged?(): void;
225
}
226
```
227
228
**Usage Example:**
229
230
```javascript
231
import { StreetViewPanorama } from "react-google-maps";
232
233
const StreetViewMap = () => {
234
const [streetViewVisible, setStreetViewVisible] = useState(false);
235
236
return (
237
<div style={{ display: "flex", height: "400px" }}>
238
<GoogleMap
239
defaultZoom={14}
240
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
241
style={{ flex: 1 }}
242
>
243
<Marker
244
position={{ lat: 37.7749, lng: -122.4194 }}
245
onClick={() => setStreetViewVisible(true)}
246
/>
247
</GoogleMap>
248
249
{streetViewVisible && (
250
<StreetViewPanorama
251
position={{ lat: 37.7749, lng: -122.4194 }}
252
pov={{ heading: 34, pitch: 10 }}
253
zoom={1}
254
options={{
255
position: { lat: 37.7749, lng: -122.4194 },
256
pov: { heading: 34, pitch: 10 },
257
zoom: 1,
258
visible: true
259
}}
260
onCloseClick={() => setStreetViewVisible(false)}
261
onPovChanged={() => {
262
console.log("Street View POV changed");
263
}}
264
style={{ flex: 1 }}
265
/>
266
)}
267
</div>
268
);
269
};
270
```
271
272
## Advanced Integration Patterns
273
274
### Custom Overlay with Map Interaction
275
276
Create interactive overlays that respond to map events:
277
278
```javascript
279
const InteractiveOverlay = ({ position, onMove }) => {
280
const [isDragging, setIsDragging] = useState(false);
281
282
return (
283
<OverlayView
284
position={position}
285
mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
286
>
287
<div
288
style={{
289
background: isDragging ? "#ff0000" : "#0000ff",
290
color: "white",
291
padding: "8px",
292
borderRadius: "4px",
293
cursor: "move",
294
userSelect: "none"
295
}}
296
onMouseDown={() => setIsDragging(true)}
297
onMouseUp={() => setIsDragging(false)}
298
onClick={(e) => {
299
e.stopPropagation();
300
if (onMove) {
301
// Calculate new position based on mouse event
302
onMove(/* new position */);
303
}
304
}}
305
>
306
Draggable Overlay
307
</div>
308
</OverlayView>
309
);
310
};
311
```
312
313
### Directions with Multiple Routes
314
315
Display and switch between multiple route options:
316
317
```javascript
318
const MultiRouteDirections = () => {
319
const [directions, setDirections] = useState([]);
320
const [selectedRoute, setSelectedRoute] = useState(0);
321
322
// Calculate multiple routes with different options
323
useEffect(() => {
324
const directionsService = new google.maps.DirectionsService();
325
const routeOptions = [
326
{ travelMode: google.maps.TravelMode.DRIVING, avoidHighways: false },
327
{ travelMode: google.maps.TravelMode.DRIVING, avoidHighways: true },
328
{ travelMode: google.maps.TravelMode.TRANSIT }
329
];
330
331
Promise.all(
332
routeOptions.map(options =>
333
new Promise(resolve => {
334
directionsService.route({
335
origin: origin,
336
destination: destination,
337
...options
338
}, resolve);
339
})
340
)
341
).then(setDirections);
342
}, []);
343
344
return (
345
<GoogleMap defaultZoom={10} defaultCenter={center}>
346
{directions[selectedRoute] && (
347
<DirectionsRenderer
348
directions={directions[selectedRoute]}
349
routeIndex={0}
350
options={{
351
polylineOptions: {
352
strokeColor: selectedRoute === 0 ? "#0000ff" :
353
selectedRoute === 1 ? "#ff0000" : "#00ff00"
354
}
355
}}
356
/>
357
)}
358
359
<div style={{ position: "absolute", top: "10px", left: "10px" }}>
360
{directions.map((_, index) => (
361
<button
362
key={index}
363
onClick={() => setSelectedRoute(index)}
364
style={{
365
backgroundColor: selectedRoute === index ? "#0066cc" : "#ccc"
366
}}
367
>
368
Route {index + 1}
369
</button>
370
))}
371
</div>
372
</GoogleMap>
373
);
374
};
375
```
376
377
### Street View Integration
378
379
Synchronize Street View with map marker positions:
380
381
```javascript
382
const SynchronizedStreetView = () => {
383
const [markerPosition, setMarkerPosition] = useState({ lat: 37.7749, lng: -122.4194 });
384
const [streetViewPov, setStreetViewPov] = useState({ heading: 34, pitch: 10 });
385
386
return (
387
<div style={{ display: "flex", height: "500px" }}>
388
<GoogleMap
389
defaultZoom={14}
390
center={markerPosition}
391
style={{ flex: 1 }}
392
>
393
<Marker
394
position={markerPosition}
395
draggable={true}
396
onDragEnd={(event) => {
397
const newPos = {
398
lat: event.latLng.lat(),
399
lng: event.latLng.lng()
400
};
401
setMarkerPosition(newPos);
402
}}
403
/>
404
</GoogleMap>
405
406
<StreetViewPanorama
407
position={markerPosition}
408
pov={streetViewPov}
409
zoom={1}
410
onPovChanged={() => {
411
// Update POV state when user changes view
412
}}
413
style={{ flex: 1 }}
414
/>
415
</div>
416
);
417
};
418
```