0
# Markers & Overlays
1
2
Components for displaying markers, info windows, and custom overlay content positioned on the map, including advanced overlay positioning and DOM content integration.
3
4
## Capabilities
5
6
### Marker Component
7
8
Places interactive markers on the map at specified positions with extensive customization and event handling options.
9
10
```typescript { .api }
11
/**
12
* Places markers on the map at specified positions
13
* Supports clustering, custom icons, and rich interaction events
14
*/
15
interface MarkerProps {
16
// Required
17
position: google.maps.LatLng | google.maps.LatLngLiteral;
18
19
children?: React.ReactNode;
20
options?: google.maps.MarkerOptions;
21
animation?: google.maps.Animation;
22
clickable?: boolean;
23
cursor?: string;
24
draggable?: boolean;
25
icon?: string | google.maps.Icon | google.maps.Symbol;
26
label?: string | google.maps.MarkerLabel;
27
opacity?: number;
28
shape?: google.maps.MarkerShape;
29
title?: string;
30
visible?: boolean;
31
zIndex?: number;
32
33
// Clustering integration
34
clusterer?: Clusterer | google.maps.MarkerClusterer;
35
noClustererRedraw?: boolean;
36
37
// Mouse events
38
onClick?: (e: google.maps.MapMouseEvent) => void;
39
onDblClick?: (e: google.maps.MapMouseEvent) => void;
40
onDrag?: (e: google.maps.MapMouseEvent) => void;
41
onDragEnd?: (e: google.maps.MapMouseEvent) => void;
42
onDragStart?: (e: google.maps.MapMouseEvent) => void;
43
onMouseDown?: (e: google.maps.MapMouseEvent) => void;
44
onMouseOut?: (e: google.maps.MapMouseEvent) => void;
45
onMouseOver?: (e: google.maps.MapMouseEvent) => void;
46
onMouseUp?: (e: google.maps.MapMouseEvent) => void;
47
onRightClick?: (e: google.maps.MapMouseEvent) => void;
48
49
// Property change events
50
onClickableChanged?: () => void;
51
onCursorChanged?: () => void;
52
onAnimationChanged?: () => void;
53
onDraggableChanged?: () => void;
54
onFlatChanged?: () => void;
55
onIconChanged?: () => void;
56
onPositionChanged?: () => void;
57
onShapeChanged?: () => void;
58
onTitleChanged?: () => void;
59
onVisibleChanged?: () => void;
60
onZindexChanged?: () => void;
61
62
// Lifecycle events
63
onLoad?: (marker: google.maps.Marker) => void;
64
onUnmount?: (marker: google.maps.Marker) => void;
65
}
66
67
function Marker(props: MarkerProps): JSX.Element;
68
```
69
70
**Usage Examples:**
71
72
```typescript
73
import React, { useState } from 'react';
74
import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';
75
76
// Basic marker
77
function BasicMarkerExample() {
78
return (
79
<LoadScript googleMapsApiKey="YOUR_API_KEY">
80
<GoogleMap
81
center={{ lat: 40.7128, lng: -74.0060 }}
82
zoom={10}
83
mapContainerStyle={{ width: '100%', height: '400px' }}
84
>
85
<Marker position={{ lat: 40.7128, lng: -74.0060 }} />
86
</GoogleMap>
87
</LoadScript>
88
);
89
}
90
91
// Interactive markers with custom icons
92
function InteractiveMarkers() {
93
const [selectedMarker, setSelectedMarker] = useState<string | null>(null);
94
95
const markers = [
96
{
97
id: 'marker1',
98
position: { lat: 40.7128, lng: -74.0060 },
99
title: 'New York City',
100
icon: 'https://maps.google.com/mapfiles/ms/icons/blue-dot.png'
101
},
102
{
103
id: 'marker2',
104
position: { lat: 40.7589, lng: -73.9851 },
105
title: 'Times Square',
106
icon: 'https://maps.google.com/mapfiles/ms/icons/red-dot.png'
107
}
108
];
109
110
return (
111
<LoadScript googleMapsApiKey="YOUR_API_KEY">
112
<GoogleMap
113
center={{ lat: 40.7128, lng: -74.0060 }}
114
zoom={12}
115
mapContainerStyle={{ width: '100%', height: '400px' }}
116
>
117
{markers.map(marker => (
118
<Marker
119
key={marker.id}
120
position={marker.position}
121
title={marker.title}
122
icon={marker.icon}
123
animation={selectedMarker === marker.id ? google.maps.Animation.BOUNCE : undefined}
124
onClick={() => setSelectedMarker(marker.id)}
125
onLoad={(markerInstance) => console.log('Marker loaded:', marker.id)}
126
/>
127
))}
128
</GoogleMap>
129
</LoadScript>
130
);
131
}
132
133
// Draggable markers with custom labels
134
function DraggableMarkers() {
135
const [markerPosition, setMarkerPosition] = useState({ lat: 40.7128, lng: -74.0060 });
136
137
const customLabel: google.maps.MarkerLabel = {
138
text: 'DRAG ME',
139
color: 'white',
140
fontSize: '14px',
141
fontWeight: 'bold'
142
};
143
144
return (
145
<LoadScript googleMapsApiKey="YOUR_API_KEY">
146
<GoogleMap
147
center={markerPosition}
148
zoom={10}
149
mapContainerStyle={{ width: '100%', height: '400px' }}
150
>
151
<Marker
152
position={markerPosition}
153
draggable={true}
154
label={customLabel}
155
title="Draggable Marker"
156
onDragEnd={(e) => {
157
if (e.latLng) {
158
const newPos = e.latLng.toJSON();
159
setMarkerPosition(newPos);
160
console.log('New position:', newPos);
161
}
162
}}
163
/>
164
</GoogleMap>
165
</LoadScript>
166
);
167
}
168
```
169
170
### MarkerF Component
171
172
Functional component variant of Marker that uses React hooks internally.
173
174
```typescript { .api }
175
/**
176
* Functional variant of Marker component using hooks internally
177
* Provides the same API as Marker but with modern React patterns
178
*/
179
function MarkerF(props: MarkerProps): JSX.Element;
180
```
181
182
### InfoWindow Component
183
184
Displays content in a popup window above the map, typically attached to markers or positioned at specific coordinates.
185
186
```typescript { .api }
187
/**
188
* Displays content in a popup window above the map
189
* Can be anchored to markers or positioned at specific coordinates
190
*/
191
interface InfoWindowProps {
192
children?: React.ReactNode;
193
anchor?: google.maps.MVCObject;
194
options?: google.maps.InfoWindowOptions;
195
position?: google.maps.LatLng | google.maps.LatLngLiteral;
196
zIndex?: number;
197
198
// Event handlers
199
onCloseClick?: () => void;
200
onDomReady?: () => void;
201
onContentChanged?: () => void;
202
onPositionChanged?: () => void;
203
onZindexChanged?: () => void;
204
205
// Lifecycle events
206
onLoad?: (infoWindow: google.maps.InfoWindow) => void;
207
onUnmount?: (infoWindow: google.maps.InfoWindow) => void;
208
}
209
210
function InfoWindow(props: InfoWindowProps): JSX.Element;
211
```
212
213
**Usage Examples:**
214
215
```typescript
216
import React, { useState } from 'react';
217
import { GoogleMap, LoadScript, Marker, InfoWindow } from '@react-google-maps/api';
218
219
// InfoWindow attached to marker
220
function MarkerWithInfoWindow() {
221
const [isOpen, setIsOpen] = useState(false);
222
const position = { lat: 40.7128, lng: -74.0060 };
223
224
return (
225
<LoadScript googleMapsApiKey="YOUR_API_KEY">
226
<GoogleMap
227
center={position}
228
zoom={10}
229
mapContainerStyle={{ width: '100%', height: '400px' }}
230
>
231
<Marker
232
position={position}
233
onClick={() => setIsOpen(true)}
234
/>
235
236
{isOpen && (
237
<InfoWindow
238
position={position}
239
onCloseClick={() => setIsOpen(false)}
240
>
241
<div>
242
<h3>New York City</h3>
243
<p>The most populous city in the United States</p>
244
<img
245
src="https://example.com/nyc.jpg"
246
alt="NYC"
247
style={{ width: '200px', height: '150px' }}
248
/>
249
</div>
250
</InfoWindow>
251
)}
252
</GoogleMap>
253
</LoadScript>
254
);
255
}
256
257
// Multiple InfoWindows with rich content
258
function MultipleInfoWindows() {
259
const [activeMarker, setActiveMarker] = useState<string | null>(null);
260
261
const locations = [
262
{
263
id: 'nyc',
264
position: { lat: 40.7128, lng: -74.0060 },
265
title: 'New York City',
266
description: 'The Big Apple',
267
image: 'https://example.com/nyc.jpg'
268
},
269
{
270
id: 'sf',
271
position: { lat: 37.7749, lng: -122.4194 },
272
title: 'San Francisco',
273
description: 'The Golden City',
274
image: 'https://example.com/sf.jpg'
275
}
276
];
277
278
return (
279
<LoadScript googleMapsApiKey="YOUR_API_KEY">
280
<GoogleMap
281
center={{ lat: 39.8283, lng: -98.5795 }}
282
zoom={4}
283
mapContainerStyle={{ width: '100%', height: '400px' }}
284
>
285
{locations.map(location => (
286
<React.Fragment key={location.id}>
287
<Marker
288
position={location.position}
289
onClick={() => setActiveMarker(location.id)}
290
/>
291
292
{activeMarker === location.id && (
293
<InfoWindow
294
position={location.position}
295
onCloseClick={() => setActiveMarker(null)}
296
options={{
297
pixelOffset: new google.maps.Size(0, -40)
298
}}
299
>
300
<div style={{ maxWidth: '300px' }}>
301
<h3>{location.title}</h3>
302
<p>{location.description}</p>
303
<img
304
src={location.image}
305
alt={location.title}
306
style={{ width: '100%', height: '150px', objectFit: 'cover' }}
307
/>
308
<button onClick={() => console.log(`More info about ${location.title}`)}>
309
Learn More
310
</button>
311
</div>
312
</InfoWindow>
313
)}
314
</React.Fragment>
315
))}
316
</GoogleMap>
317
</LoadScript>
318
);
319
}
320
```
321
322
### InfoWindowF Component
323
324
Functional component variant of InfoWindow that uses React hooks internally.
325
326
```typescript { .api }
327
/**
328
* Functional variant of InfoWindow component using hooks internally
329
* Provides the same API as InfoWindow but with modern React patterns
330
*/
331
function InfoWindowF(props: InfoWindowProps): JSX.Element;
332
```
333
334
### InfoBox Component
335
336
Enhanced info window component with additional styling options and features beyond the standard InfoWindow.
337
338
```typescript { .api }
339
/**
340
* Enhanced info window with additional styling options
341
* Provides more customization than standard InfoWindow
342
*/
343
interface InfoBoxProps {
344
children?: React.ReactNode;
345
options?: InfoBoxOptions;
346
position?: google.maps.LatLng | google.maps.LatLngLiteral;
347
visible?: boolean;
348
zIndex?: number;
349
350
// Event handlers
351
onCloseClick?: () => void;
352
onDomReady?: () => void;
353
onContentChanged?: () => void;
354
onPositionChanged?: () => void;
355
356
// Lifecycle events
357
onLoad?: (infoBox: InfoBox) => void;
358
onUnmount?: (infoBox: InfoBox) => void;
359
}
360
361
interface InfoBoxOptions {
362
alignBottom?: boolean;
363
boxClass?: string;
364
boxStyle?: React.CSSProperties;
365
closeBoxMargin?: string;
366
closeBoxURL?: string;
367
content?: string | Node;
368
disableAutoPan?: boolean;
369
enableEventPropagation?: boolean;
370
infoBoxClearance?: google.maps.Size;
371
isHidden?: boolean;
372
maxWidth?: number;
373
pixelOffset?: google.maps.Size;
374
position?: google.maps.LatLng | google.maps.LatLngLiteral;
375
zIndex?: number;
376
}
377
378
function InfoBox(props: InfoBoxProps): JSX.Element;
379
```
380
381
**Usage Examples:**
382
383
```typescript
384
import React, { useState } from 'react';
385
import { GoogleMap, LoadScript, Marker, InfoBox } from '@react-google-maps/api';
386
387
function StyledInfoBox() {
388
const [isOpen, setIsOpen] = useState(false);
389
const position = { lat: 40.7128, lng: -74.0060 };
390
391
const infoBoxOptions: InfoBoxOptions = {
392
boxStyle: {
393
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
394
color: 'white',
395
padding: '15px',
396
borderRadius: '10px',
397
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
398
fontFamily: 'Arial, sans-serif'
399
},
400
closeBoxMargin: '5px',
401
closeBoxURL: 'https://example.com/close-icon.png',
402
pixelOffset: new google.maps.Size(-150, -50),
403
maxWidth: 300
404
};
405
406
return (
407
<LoadScript googleMapsApiKey="YOUR_API_KEY">
408
<GoogleMap
409
center={position}
410
zoom={10}
411
mapContainerStyle={{ width: '100%', height: '400px' }}
412
>
413
<Marker
414
position={position}
415
onClick={() => setIsOpen(true)}
416
/>
417
418
{isOpen && (
419
<InfoBox
420
position={position}
421
options={infoBoxOptions}
422
onCloseClick={() => setIsOpen(false)}
423
>
424
<div>
425
<h3 style={{ margin: '0 0 10px 0' }}>Styled InfoBox</h3>
426
<p style={{ margin: '0' }}>
427
This InfoBox has custom styling and enhanced features!
428
</p>
429
</div>
430
</InfoBox>
431
)}
432
</GoogleMap>
433
</LoadScript>
434
);
435
}
436
```
437
438
### InfoBoxF Component
439
440
Functional component variant of InfoBox that uses React hooks internally.
441
442
```typescript { .api }
443
/**
444
* Functional variant of InfoBox component using hooks internally
445
*/
446
function InfoBoxF(props: InfoBoxProps): JSX.Element;
447
```
448
449
### OverlayView Component
450
451
Custom overlay component that displays DOM content positioned precisely on the map using geographic coordinates.
452
453
```typescript { .api }
454
/**
455
* Custom overlay that displays DOM content positioned on the map
456
* Allows precise positioning of React components at geographic coordinates
457
*/
458
interface OverlayViewProps {
459
children?: React.ReactNode;
460
position: google.maps.LatLng | google.maps.LatLngLiteral;
461
pane?: string;
462
mapPaneName?: string;
463
getPixelPositionOffset?: (width: number, height: number) => { x: number; y: number };
464
465
// Lifecycle events
466
onLoad?: (overlayView: google.maps.OverlayView) => void;
467
onUnmount?: (overlayView: google.maps.OverlayView) => void;
468
}
469
470
function OverlayView(props: OverlayViewProps): JSX.Element;
471
472
// Overlay pane constants
473
declare const FLOAT_PANE: string;
474
declare const MAP_PANE: string;
475
declare const MARKER_LAYER: string;
476
declare const OVERLAY_LAYER: string;
477
declare const OVERLAY_MOUSE_TARGET: string;
478
```
479
480
**Usage Examples:**
481
482
```typescript
483
import React from 'react';
484
import {
485
GoogleMap,
486
LoadScript,
487
OverlayView,
488
OVERLAY_MOUSE_TARGET
489
} from '@react-google-maps/api';
490
491
// Custom overlay with precise positioning
492
function CustomOverlayExample() {
493
const position = { lat: 40.7128, lng: -74.0060 };
494
495
const getPixelPositionOffset = (width: number, height: number) => ({
496
x: -(width / 2),
497
y: -(height / 2)
498
});
499
500
return (
501
<LoadScript googleMapsApiKey="YOUR_API_KEY">
502
<GoogleMap
503
center={position}
504
zoom={15}
505
mapContainerStyle={{ width: '100%', height: '400px' }}
506
>
507
<OverlayView
508
position={position}
509
pane={OVERLAY_MOUSE_TARGET}
510
getPixelPositionOffset={getPixelPositionOffset}
511
>
512
<div style={{
513
background: 'white',
514
border: '2px solid #ff6b6b',
515
borderRadius: '20px',
516
padding: '10px',
517
fontSize: '14px',
518
fontWeight: 'bold',
519
color: '#333',
520
boxShadow: '0 2px 10px rgba(0,0,0,0.3)',
521
cursor: 'pointer'
522
}}>
523
Custom Overlay Content
524
<div style={{ fontSize: '12px', fontWeight: 'normal', marginTop: '5px' }}>
525
Positioned at: {position.lat.toFixed(4)}, {position.lng.toFixed(4)}
526
</div>
527
</div>
528
</OverlayView>
529
</GoogleMap>
530
</LoadScript>
531
);
532
}
533
534
// Multiple overlays with different panes
535
function MultipleOverlays() {
536
const locations = [
537
{ lat: 40.7128, lng: -74.0060, label: 'NYC' },
538
{ lat: 40.7589, lng: -73.9851, label: 'Times Square' },
539
{ lat: 40.7505, lng: -73.9934, label: 'Empire State' }
540
];
541
542
return (
543
<LoadScript googleMapsApiKey="YOUR_API_KEY">
544
<GoogleMap
545
center={{ lat: 40.7128, lng: -74.0060 }}
546
zoom={13}
547
mapContainerStyle={{ width: '100%', height: '400px' }}
548
>
549
{locations.map((location, index) => (
550
<OverlayView
551
key={index}
552
position={location}
553
pane={OVERLAY_MOUSE_TARGET}
554
getPixelPositionOffset={(w, h) => ({ x: -w/2, y: -h })}
555
>
556
<div style={{
557
background: '#4285f4',
558
color: 'white',
559
padding: '8px 12px',
560
borderRadius: '16px',
561
fontSize: '12px',
562
fontWeight: 'bold',
563
boxShadow: '0 2px 8px rgba(0,0,0,0.3)',
564
whiteSpace: 'nowrap'
565
}}>
566
{location.label}
567
</div>
568
</OverlayView>
569
))}
570
</GoogleMap>
571
</LoadScript>
572
);
573
}
574
```
575
576
### OverlayViewF Component
577
578
Functional component variant of OverlayView that uses React hooks internally.
579
580
```typescript { .api }
581
/**
582
* Functional variant of OverlayView component using hooks internally
583
*/
584
function OverlayViewF(props: OverlayViewProps): JSX.Element;
585
```
586
587
### GroundOverlay Component
588
589
Displays images overlaid on the map, anchored to geographic coordinates and scaled appropriately.
590
591
```typescript { .api }
592
/**
593
* Displays images overlaid on the map
594
* Images are anchored to geographic coordinates and scaled with the map
595
*/
596
interface GroundOverlayProps {
597
url: string;
598
bounds: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral;
599
options?: google.maps.GroundOverlayOptions;
600
opacity?: number;
601
clickable?: boolean;
602
603
// Event handlers
604
onClick?: (e: google.maps.MapMouseEvent) => void;
605
onDblClick?: (e: google.maps.MapMouseEvent) => void;
606
607
// Lifecycle events
608
onLoad?: (groundOverlay: google.maps.GroundOverlay) => void;
609
onUnmount?: (groundOverlay: google.maps.GroundOverlay) => void;
610
}
611
612
function GroundOverlay(props: GroundOverlayProps): JSX.Element;
613
```
614
615
**Usage Examples:**
616
617
```typescript
618
import React, { useState } from 'react';
619
import { GoogleMap, LoadScript, GroundOverlay } from '@react-google-maps/api';
620
621
function GroundOverlayExample() {
622
const [opacity, setOpacity] = useState(0.8);
623
624
const bounds = {
625
north: 40.7739,
626
south: 40.7517,
627
east: -73.9657,
628
west: -73.9963
629
};
630
631
return (
632
<LoadScript googleMapsApiKey="YOUR_API_KEY">
633
<div>
634
<div style={{ padding: '10px' }}>
635
<label>
636
Opacity:
637
<input
638
type="range"
639
min="0"
640
max="1"
641
step="0.1"
642
value={opacity}
643
onChange={(e) => setOpacity(parseFloat(e.target.value))}
644
/>
645
{opacity}
646
</label>
647
</div>
648
649
<GoogleMap
650
center={{ lat: 40.7628, lng: -73.981 }}
651
zoom={14}
652
mapContainerStyle={{ width: '100%', height: '400px' }}
653
>
654
<GroundOverlay
655
url="https://example.com/central-park-overlay.png"
656
bounds={bounds}
657
opacity={opacity}
658
clickable={true}
659
onClick={() => console.log('Ground overlay clicked')}
660
onLoad={() => console.log('Ground overlay loaded')}
661
/>
662
</GoogleMap>
663
</div>
664
</LoadScript>
665
);
666
}
667
```
668
669
### GroundOverlayF Component
670
671
Functional component variant of GroundOverlay that uses React hooks internally.
672
673
```typescript { .api }
674
/**
675
* Functional variant of GroundOverlay component using hooks internally
676
*/
677
function GroundOverlayF(props: GroundOverlayProps): JSX.Element;
678
```