Extended functionality including heatmaps, map layers, Google Maps API integration, and advanced configuration options for complex mapping applications.
Display data density using Google Maps heatmap layer with custom styling and data points.
/**
* Heatmap configuration for visualizing data density
*/
interface HeatmapConfig {
positions: HeatmapPosition[];
options?: HeatmapOptions;
}
interface HeatmapPosition {
lat: number;
lng: number;
weight?: number; // Defaults to 1
}
interface HeatmapOptions {
radius?: number;
opacity?: number;
gradient?: string[];
maxIntensity?: number;
dissipating?: boolean;
[key: string]: any; // Additional Google Maps heatmap options
}
interface GoogleMapReactHeatmapProps extends GoogleMapReactProps {
heatmap?: HeatmapConfig;
heatmapLibrary?: boolean; // Set to true to load visualization library
}Usage Examples:
import GoogleMapReact from 'google-map-react';
// Basic heatmap
const heatmapData = [
{ lat: 37.782551, lng: -122.445368, weight: 5 },
{ lat: 37.782745, lng: -122.444586, weight: 3 },
{ lat: 37.782842, lng: -122.443688, weight: 8 },
{ lat: 37.782919, lng: -122.442815, weight: 2 }
];
<GoogleMapReact
bootstrapURLKeys={{
key: "YOUR_API_KEY",
libraries: ['visualization'] // Required for heatmaps
}}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={13}
heatmap={{
positions: heatmapData,
options: {
radius: 20,
opacity: 0.8
}
}}
/>
// Advanced heatmap with custom gradient
<GoogleMapReact
bootstrapURLKeys={{
key: "YOUR_API_KEY",
libraries: ['visualization']
}}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={13}
heatmap={{
positions: heatmapData,
options: {
radius: 40,
opacity: 0.6,
gradient: [
'rgba(0, 255, 255, 0)',
'rgba(0, 255, 255, 1)',
'rgba(0, 191, 255, 1)',
'rgba(0, 127, 255, 1)',
'rgba(0, 63, 255, 1)',
'rgba(0, 0, 255, 1)',
'rgba(0, 0, 223, 1)',
'rgba(0, 0, 191, 1)',
'rgba(0, 0, 159, 1)',
'rgba(0, 0, 127, 1)',
'rgba(63, 0, 91, 1)',
'rgba(127, 0, 63, 1)',
'rgba(191, 0, 31, 1)',
'rgba(255, 0, 0, 1)'
],
maxIntensity: 10,
dissipating: false
}
}}
/>Add Google Maps layers like traffic and transit information.
type LayerType = 'TrafficLayer' | 'TransitLayer' | 'BicyclingLayer' | string;
interface GoogleMapReactLayerProps extends GoogleMapReactProps {
layerTypes?: LayerType[];
}Usage Examples:
// Traffic and transit layers
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={12}
layerTypes={['TrafficLayer', 'TransitLayer']}
/>
// Dynamic layer control
function LayerControlMap() {
const [activeLayers, setActiveLayers] = useState([]);
const toggleLayer = (layer) => {
setActiveLayers(prev =>
prev.includes(layer)
? prev.filter(l => l !== layer)
: [...prev, layer]
);
};
return (
<div>
<div>
<button onClick={() => toggleLayer('TrafficLayer')}>
Traffic Layer
</button>
<button onClick={() => toggleLayer('TransitLayer')}>
Transit Layer
</button>
</div>
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={12}
layerTypes={activeLayers}
/>
</div>
);
}Direct access to Google Maps API objects for advanced functionality.
interface GoogleApiLoadedHandler {
(args: {
map: google.maps.Map;
maps: typeof google.maps;
}): void;
}
interface GoogleMapReactApiProps extends GoogleMapReactProps {
onGoogleApiLoaded?: GoogleApiLoadedHandler;
yesIWantToUseGoogleMapApiInternals: true; // Required for API access
}Usage Examples:
// Custom markers and overlays
function AdvancedMapFeatures() {
const [map, setMap] = useState(null);
const [maps, setMaps] = useState(null);
const [markers, setMarkers] = useState([]);
const handleApiLoaded = ({ map, maps }) => {
setMap(map);
setMaps(maps);
// Create custom marker
const marker = new maps.Marker({
position: { lat: 37.7749, lng: -122.4194 },
map: map,
title: 'Custom Google Marker',
icon: {
url: 'path/to/custom-icon.png',
scaledSize: new maps.Size(40, 40)
}
});
// Add info window
const infoWindow = new maps.InfoWindow({
content: '<div>Custom Info Window</div>'
});
marker.addListener('click', () => {
infoWindow.open(map, marker);
});
setMarkers([marker]);
};
return (
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={10}
onGoogleApiLoaded={handleApiLoaded}
yesIWantToUseGoogleMapApiInternals
/>
);
}
// Drawing tools
function DrawingMap() {
const handleApiLoaded = ({ map, maps }) => {
const drawingManager = new maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
position: maps.ControlPosition.TOP_CENTER,
drawingModes: [
maps.drawing.OverlayType.MARKER,
maps.drawing.OverlayType.CIRCLE,
maps.drawing.OverlayType.POLYGON,
maps.drawing.OverlayType.POLYLINE,
maps.drawing.OverlayType.RECTANGLE
]
}
});
drawingManager.setMap(map);
maps.event.addListener(drawingManager, 'overlaycomplete', (event) => {
console.log('Drawing completed:', event.type, event.overlay);
});
};
return (
<GoogleMapReact
bootstrapURLKeys={{
key: "YOUR_API_KEY",
libraries: ['drawing']
}}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={10}
onGoogleApiLoaded={handleApiLoaded}
yesIWantToUseGoogleMapApiInternals
/>
);
}Extended configuration options for specialized use cases.
interface AdvancedConfigProps extends GoogleMapReactProps {
resetBoundsOnResize?: boolean;
shouldUnregisterMapOnUnmount?: boolean;
margin?: [number, number, number, number];
overlayViewDivStyle?: { [key: string]: any };
experimental?: boolean;
googleMapLoader?: (bootstrapURLKeys: any, heatmapLibrary: boolean) => Promise<any>;
}Usage Examples:
// Responsive map that resets bounds on resize
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={10}
resetBoundsOnResize={true}
style={{ width: '100%', height: '100vh' }}
/>
// Map with margin for bounds calculations
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={10}
margin={[60, 60, 60, 60]} // top, right, bottom, left
onChange={({ center, zoom, bounds, marginBounds }) => {
console.log('Regular bounds:', bounds);
console.log('Margin bounds:', marginBounds);
}}
/>
// Custom Google Maps loader
const customLoader = (bootstrapURLKeys, heatmapLibrary) => {
return new Promise((resolve, reject) => {
// Custom loading logic
if (window.google && window.google.maps) {
resolve(window.google.maps);
} else {
// Load Google Maps API with custom parameters
const script = document.createElement('script');
script.src = `https://maps.googleapis.com/maps/api/js?key=${bootstrapURLKeys.key}&libraries=${heatmapLibrary ? 'visualization' : ''}`;
script.onload = () => resolve(window.google.maps);
script.onerror = reject;
document.head.appendChild(script);
}
});
};
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={10}
googleMapLoader={customLoader}
/>
// Custom overlay div styling
<GoogleMapReact
bootstrapURLKeys={{ key: "YOUR_API_KEY" }}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={10}
overlayViewDivStyle={{
backgroundColor: 'rgba(255, 255, 255, 0.8)',
border: '2px solid #333',
borderRadius: '8px',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
}}
/>Combine heatmaps with real-time data updates.
function RealTimeHeatmap() {
const [heatmapData, setHeatmapData] = useState([]);
useEffect(() => {
const interval = setInterval(async () => {
try {
const response = await fetch('/api/real-time-data');
const data = await response.json();
setHeatmapData(data.map(point => ({
lat: point.latitude,
lng: point.longitude,
weight: point.intensity
})));
} catch (error) {
console.error('Failed to fetch real-time data:', error);
}
}, 5000); // Update every 5 seconds
return () => clearInterval(interval);
}, []);
return (
<GoogleMapReact
bootstrapURLKeys={{
key: "YOUR_API_KEY",
libraries: ['visualization']
}}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={12}
heatmap={{
positions: heatmapData,
options: {
radius: 30,
opacity: 0.7,
dissipating: true
}
}}
/>
);
}Combine multiple data layers and visualization techniques.
function MultiLayerMap() {
const [showTraffic, setShowTraffic] = useState(false);
const [showHeatmap, setShowHeatmap] = useState(true);
const [data, setData] = useState([]);
const handleApiLoaded = ({ map, maps }) => {
// Add custom overlay
const overlay = new maps.OverlayView();
overlay.onAdd = function() {
const div = document.createElement('div');
div.style.position = 'absolute';
div.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
div.style.border = '2px solid red';
div.style.width = '100px';
div.style.height = '50px';
const panes = this.getPanes();
panes.overlayLayer.appendChild(div);
};
overlay.draw = function() {
const projection = this.getProjection();
const position = projection.fromLatLngToDivPixel(
new maps.LatLng(37.7749, -122.4194)
);
const div = this.getPanes().overlayLayer.firstChild;
div.style.left = position.x + 'px';
div.style.top = position.y + 'px';
};
overlay.setMap(map);
};
return (
<div>
<div>
<button onClick={() => setShowTraffic(!showTraffic)}>
{showTraffic ? 'Hide' : 'Show'} Traffic
</button>
<button onClick={() => setShowHeatmap(!showHeatmap)}>
{showHeatmap ? 'Hide' : 'Show'} Heatmap
</button>
</div>
<GoogleMapReact
bootstrapURLKeys={{
key: "YOUR_API_KEY",
libraries: ['visualization']
}}
defaultCenter={{ lat: 37.7749, lng: -122.4194 }}
defaultZoom={12}
layerTypes={showTraffic ? ['TrafficLayer'] : []}
heatmap={showHeatmap ? {
positions: data,
options: { radius: 25, opacity: 0.6 }
} : undefined}
onGoogleApiLoaded={handleApiLoaded}
yesIWantToUseGoogleMapApiInternals
>
{/* Regular React markers */}
<Marker lat={37.7749} lng={-122.4194} text="SF" />
</GoogleMapReact>
</div>
);
}