Skip to content

Commit

Permalink
docs: add example for MapControl component
Browse files Browse the repository at this point in the history
  • Loading branch information
usefulthink committed Nov 9, 2023
1 parent ae9c104 commit b132cbf
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 1 deletion.
35 changes: 35 additions & 0 deletions examples/map-control/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Custom Map Control Example

This is an example to show how to add custom map-controls.

## 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 an 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
30 changes: 30 additions & 0 deletions examples/map-control/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!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: Custom Map Control</title>

<style>
body {
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
</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>
13 changes: 13 additions & 0 deletions examples/map-control/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"dependencies": {
"@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"
}
}
67 changes: 67 additions & 0 deletions examples/map-control/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, {useMemo, useState} from 'react';
import {createRoot} from 'react-dom/client';

import {
APIProvider,
ControlPosition,
Map,
MapControl
} from '@vis.gl/react-google-maps';

import ControlPanel from './control-panel';
import {CustomZoomControl} from './custom-zoom-control';

const API_KEY = process.env.GOOGLE_MAPS_API_KEY as string;

const App = () => {
const [controlPosition, setControlControlPosition] =
useState<ControlPosition>(ControlPosition.LEFT_BOTTOM);

const [zoom, setZoom] = useState(4);
const center = useMemo(() => ({lat: 0, lng: 20}), []);

return (
<APIProvider apiKey={API_KEY}>
<Map
disableDefaultUI={true}
gestureHandling={'greedy'}
mapId={'49ae42fed52588c3'}
center={center}
zoom={zoom}
onZoomChanged={ev => setZoom(ev.detail.zoom)}>
<MapControl position={ControlPosition.TOP_LEFT}>
<div
style={{
background: 'white',
padding: '1em'
}}>
Zoom: {zoom.toFixed(2)}
</div>
</MapControl>

<CustomZoomControl
controlPosition={controlPosition}
zoom={zoom}
onZoomChange={zoom => setZoom(zoom)}
/>
</Map>

<ControlPanel
position={controlPosition}
onControlPositionChange={p => setControlControlPosition(p)}
/>
</APIProvider>
);
};

export default App;

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

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

import {ControlPosition} from '@vis.gl/react-google-maps';

export type ControlPanelProps = {
position: ControlPosition;
onControlPositionChange: (position: ControlPosition) => void;
};

function ControlPanel({position, onControlPositionChange}: ControlPanelProps) {
const positionOptions: {key: string; value: ControlPosition}[] = [];

for (const [p, v] of Object.entries(ControlPosition)) {
positionOptions.push({key: p, value: v as ControlPosition});
}

return (
<div className="control-panel">
<h3>MapControl Example</h3>
<p>
Demonstrates how to use the <code>&lt;MapControl&gt;</code> component to
add custom control components to the map.
</p>

<div>
<label>Control Position</label>
<select
value={position}
onChange={ev =>
onControlPositionChange(Number(ev.target.value) as ControlPosition)
}>
{positionOptions.map(({key, value}) => (
<option key={key} value={value}>
{key}
</option>
))}
</select>
</div>

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

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

export default React.memo(ControlPanel);
38 changes: 38 additions & 0 deletions examples/map-control/src/custom-zoom-control.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {ControlPosition, MapControl} from '@vis.gl/react-google-maps';
import React from 'react';

type CustomZoomControlProps = {
controlPosition: ControlPosition;
zoom: number;
onZoomChange: (zoom: number) => void;
};

export const CustomZoomControl = ({
controlPosition,
zoom,
onZoomChange
}: CustomZoomControlProps) => {
return (
<MapControl position={controlPosition}>
<div
style={{
margin: '10px',
padding: '1em',
background: 'rgba(255,255,255,0.4)',
display: 'flex',
flexFlow: 'column nowrap'
}}>
<label htmlFor={'zoom'}>This is a custom zoom control!</label>
<input
id={'zoom'}
type={'range'}
min={1}
max={18}
step={'any'}
value={zoom}
onChange={ev => onZoomChange(ev.target.valueAsNumber)}
/>
</div>
</MapControl>
);
};
11 changes: 11 additions & 0 deletions examples/map-control/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {defineConfig, loadEnv} from 'vite';

export default defineConfig(({mode}) => {
const {GOOGLE_MAPS_API_KEY = ''} = loadEnv(mode, process.cwd(), '');

return {
define: {
'process.env.GOOGLE_MAPS_API_KEY': JSON.stringify(GOOGLE_MAPS_API_KEY)
}
};
});
7 changes: 6 additions & 1 deletion website/src/examples-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ const sidebars = {
{
type: 'category',
label: 'Examples',
items: ['basic-map', 'markers-and-infowindows', 'change-map-id']
items: [
'basic-map',
'markers-and-infowindows',
'change-map-id',
'map-control'
]
}
]
};
Expand Down
5 changes: 5 additions & 0 deletions website/src/examples/map-control.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Custom Map Controls

import App from 'website-examples/map-control/src/app';

<App />
Binary file added website/static/images/examples/map-control.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b132cbf

Please sign in to comment.