Skip to content

Commit

Permalink
docs: add new directions example (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
leighhalliday authored Nov 11, 2023
1 parent f01d4ea commit b87ba05
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 1 deletion.
39 changes: 39 additions & 0 deletions examples/directions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Basic Google Maps Setup Example

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

This is an example which shows how to use `useMapsLibrary` to load the `routes` library, and then use `DirectionsService` and `DirectionsRenderer` to find and display a route on a map.

It allows the user to choose alternative routes, updating the route being rendered on the 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 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
68 changes: 68 additions & 0 deletions examples/directions/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!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:</title>

<style>
body {
font-size: 16px;
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
h1 {
padding: 0.25rem 0px;
font-size: 1.5rem;
}
h2 {
padding: 0.25rem 0px;
font-size: 1.25rem;
}
p {
font-size: 0.8rem;
padding: 0px;
padding-bottom: 0.25rem;
margin: 0px;
}
.directions {
position: absolute;
width: 275px;
top: 0px;
right: 0px;
padding: 1.25rem;
padding-top: 0px;
margin: 0.25rem;
color: white;
background-color: #2d3748;
border-radius: 0.25rem;
}
ul {
padding: 0px;
padding-left: 1.5rem;
margin: 0px;
}
li button {
color: #f6e05e;
background: none;
border: none;
cursor: pointer;
}
</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/directions/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"
}
}
100 changes: 100 additions & 0 deletions examples/directions/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, {useEffect, useState} from 'react';
import {createRoot} from 'react-dom/client';

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

const API_KEY = process.env.GOOGLE_MAPS_API_KEY as string;

const App = () => (
<APIProvider apiKey={API_KEY}>
<Map center={{lat: 43.65, lng: -79.38}} zoom={9} fullscreenControl={false}>
<Directions />
</Map>
</APIProvider>
);

function Directions() {
const map = useMap();
const routesLibrary = useMapsLibrary('routes');
const [directionsService, setDirectionsService] =
useState<google.maps.DirectionsService>();
const [directionsRenderer, setDirectionsRenderer] =
useState<google.maps.DirectionsRenderer>();
const [routes, setRoutes] = useState<google.maps.DirectionsRoute[]>([]);
const [routeIndex, setRouteIndex] = useState(0);
const selected = routes[routeIndex];
const leg = selected?.legs[0];

// Initialize directions service and renderer
useEffect(() => {
if (!routesLibrary || !map) return;
setDirectionsService(new routesLibrary.DirectionsService());
setDirectionsRenderer(new routesLibrary.DirectionsRenderer({map}));
}, [routesLibrary, map]);

// Use directions service
useEffect(() => {
if (!directionsService || !directionsRenderer) return;

directionsService
.route({
origin: '100 Front St, Toronto ON',
destination: '500 College St, Toronto ON',
travelMode: google.maps.TravelMode.DRIVING,
provideRouteAlternatives: true
})
.then(response => {
directionsRenderer.setDirections(response);
setRoutes(response.routes);
});

return () => directionsRenderer.setMap(null);
}, [directionsService, directionsRenderer]);

// Update direction route
useEffect(() => {
if (!directionsRenderer) return;
directionsRenderer.setRouteIndex(routeIndex);
}, [routeIndex, directionsRenderer]);

if (!leg) return null;

return (
<div className="directions">
<h2>{selected.summary}</h2>
<p>
{leg.start_address.split(',')[0]} to {leg.end_address.split(',')[0]}
</p>
<p>Distance: {leg.distance?.text}</p>
<p>Duration: {leg.duration?.text}</p>

<h2>Other Routes</h2>
<ul>
{routes.map((route, index) => (
<li key={route.summary}>
<button onClick={() => setRouteIndex(index)}>
{route.summary}
</button>
</li>
))}
</ul>
</div>
);
}

export default App;

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

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

function ControlPanel() {
return (
<div className="control-panel">
<h3>Directions</h3>
<p>
Loading the routes library to render directions on the map using
DirectionsService and DirectionsRenderer.
</p>

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

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

export default React.memo(ControlPanel);
11 changes: 11 additions & 0 deletions examples/directions/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)
}
};
});
3 changes: 2 additions & 1 deletion website/src/examples-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const sidebars = {
'basic-map',
'markers-and-infowindows',
'change-map-styles',
'map-control'
'map-control',
'directions'
]
}
]
Expand Down
5 changes: 5 additions & 0 deletions website/src/examples/directions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Directions

import App from 'website-examples/directions/src/app';

<App />
Binary file added website/static/images/examples/directions.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 b87ba05

Please sign in to comment.