Skip to content

Commit

Permalink
docs: new example for marker clustering (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
leighhalliday committed Nov 13, 2023
1 parent 1dc1584 commit be85be0
Show file tree
Hide file tree
Showing 10 changed files with 723 additions and 3 deletions.
4 changes: 2 additions & 2 deletions examples/change-map-styles/src/control-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ function ControlPanel({

<div className="links">
<a
href="https://codesandbox.io/s/github/visgl/react-google-maps/tree/main/examples/change-map-id"
href="https://codesandbox.io/s/github/visgl/react-google-maps/tree/main/examples/change-map-styles"
target="_new">
Try on CodeSandbox ↗
</a>

<a
href="https://github.com/visgl/react-google-maps/tree/main/examples/change-map-id"
href="https://github.com/visgl/react-google-maps/tree/main/examples/change-map-styles"
target="_new">
View Code ↗
</a>
Expand Down
2 changes: 1 addition & 1 deletion examples/directions/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>Example:</title>
<title>Example: Directions</title>

<style>
body {
Expand Down
37 changes: 37 additions & 0 deletions examples/marker-clustering/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Marker Clustering Example

![image](https://raw.githubusercontent.com/visgl/react-google-maps/main/website/static/images/examples/marker-clustering.jpg)

This is an example of how to use the [MarkerClusterer](https://github.com/googlemaps/js-markerclusterer) library from Google to cluster markers on a map.

## Google Maps API key

This example does not come with an API key. Running the examples locally requires a valid API key for the Google Maps Platform.
See [the official documentation][get-api-key] on how to create and configure your own key.

The API key has to be provided via the environment variable `GOOGLE_MAPS_API_KEY`. This can be done by creating a
file named `.env` in the example directory with the following content:

```shell title=".env"
GOOGLE_MAPS_API_KEY="<YOUR API KEY HERE>"
```

If you are on the CodeSandbox playground you can also choose to [provide the API key like this](https://codesandbox.io/docs/learn/environment/secrets)

## Development

Go into the example-directory and run

```shell
npm install
```

To start the example with the local library run

```shell
npm run start-local
```

The regular `npm start` task is only used for the standalone versions of the example (CodeSandbox for example)

[get-api-key]: https://developers.google.com/maps/documentation/javascript/get-api-key
34 changes: 34 additions & 0 deletions examples/marker-clustering/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>Example: Marker Clustering</title>

<style>
body {
font-size: 16px;
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
.tree {
font-size: 2rem;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module">
import '@vis.gl/react-google-maps/examples.css';
import {renderToDom} from './src/app';

renderToDom(document.querySelector('#app'));
</script>
</body>
</html>
14 changes: 14 additions & 0 deletions examples/marker-clustering/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"dependencies": {
"@googlemaps/markerclusterer": "^2.5.1",
"@vis.gl/react-google-maps": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"vite": "^4.3.9"
},
"scripts": {
"start": "vite",
"start-local": "vite --config ../vite.config.local.js",
"build": "vite build"
}
}
88 changes: 88 additions & 0 deletions examples/marker-clustering/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, {useEffect, useState, useRef} from 'react';
import {createRoot} from 'react-dom/client';

import {
APIProvider,
Map,
useMap,
AdvancedMarker
} from '@vis.gl/react-google-maps';
import {MarkerClusterer} from '@googlemaps/markerclusterer';
import type {Marker} from '@googlemaps/markerclusterer';
import trees from './trees';

const API_KEY = process.env.GOOGLE_MAPS_API_KEY as string;

const App = () => (
<APIProvider apiKey={API_KEY}>
<Map
mapId={'bf51a910020fa25a'}
center={{lat: 43.64, lng: -79.41}}
zoom={10}>
<Markers points={trees} />
</Map>
</APIProvider>
);

type Point = google.maps.LatLngLiteral & {key: string};
type Props = {points: Point[]};

const Markers = ({points}: Props) => {
const map = useMap();
const [markers, setMarkers] = useState<{[key: string]: Marker}>({});
const clusterer = useRef<MarkerClusterer | null>(null);

// Initialize MarkerClusterer
useEffect(() => {
if (!map) return;
if (!clusterer.current) {
clusterer.current = new MarkerClusterer({map});
}
}, [map]);

// Update markers
useEffect(() => {
clusterer.current?.clearMarkers();
clusterer.current?.addMarkers(Object.values(markers));
}, [markers]);

const setMarkerRef = (marker: Marker | null, key: string) => {
if (marker && markers[key]) return;
if (!marker && !markers[key]) return;

setMarkers(prev => {
if (marker) {
return {...prev, [key]: marker};
} else {
const newMarkers = {...prev};
delete newMarkers[key];
return newMarkers;
}
});
};

return (
<>
{points.map(point => (
<AdvancedMarker
position={point}
key={point.key}
ref={marker => setMarkerRef(marker, point.key)}>
<span className="tree">🌳</span>
</AdvancedMarker>
))}
</>
);
};

export default App;

export function renderToDom(container: HTMLElement) {
const root = createRoot(container);

root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
26 changes: 26 additions & 0 deletions examples/marker-clustering/src/control-panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';

function ControlPanel() {
return (
<div className="control-panel">
<h3>Marker Clustering</h3>
<p>Using MarkerClusterer to cluster Markers on a map.</p>

<div className="links">
<a
href="https://codesandbox.io/s/github/visgl/react-google-maps/tree/main/examples/marker-clustering"
target="_new">
Try on CodeSandbox ↗
</a>

<a
href="https://github.com/visgl/react-google-maps/tree/main/examples/marker-clustering"
target="_new">
View Code ↗
</a>
</div>
</div>
);
}

export default React.memo(ControlPanel);
Loading

0 comments on commit be85be0

Please sign in to comment.