Skip to content

docs(example): map 3d markers example #765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions examples/map-3d-markers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 3D Maps with Markers Example

This example implements a new `Map3D` component that renders
a 3D Globe based on the new experimental [`Map3DElement`][gmp-map3d-overview]
web-component.

The map contains basic [`Marker3DElements`][gmp-map3d-marker-add] as well as markers with a custom pin and a 3D model.

[gmp-map3d-overview]: https://developers.google.com/maps/documentation/javascript/3d-maps-overview
[gmp-map3d-marker-add]: https://developers.google.com/maps/documentation/javascript/3d/marker-add

## 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
73 changes: 73 additions & 0 deletions examples/map-3d-markers/config/marker-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"basic": {
"markerOptions": {
"position": {
"lat": 40.704876,
"lng": -73.995379,
"altitude": 50
},
"altitudeMode": "RELATIVE_TO_GROUND"
}
},
"basicExtruded": {
"markerOptions": {
"position": {
"lat": 40.704118,
"lng": -73.994371,
"altitude": 150
},
"extruded": true,
"altitudeMode": "RELATIVE_TO_GROUND"
}
},
"basicColored": {
"markerOptions": {
"position": {
"lat": 40.705666,
"lng": -73.996382,
"altitude": 50
},
"altitudeMode": "RELATIVE_TO_GROUND"
},
"pinOptions": {
"borderColor": "#0D652D",
"background": "#34A853",
"glyphColor": "white"
}
},
"customLogo": {
"markerOptions": {
"position": {
"lat": 40.706461,
"lng": -73.997409,
"altitude": 50
},
"altitudeMode": "RELATIVE_TO_GROUND"
},
"pinOptions": {
"borderColor": "white",
"background": "white",
"glyph": "https://www.gstatic.com/images/branding/productlogos/maps/v7/192px.svg"
}
},
"svg": {
"markerOptions": {
"position": {
"lat": 40.707275,
"lng": -73.998332,
"altitude": 80
},
"altitudeMode": "RELATIVE_TO_GROUND"
}
},
"model3d": {
"markerOptions": {
"position": {
"lat": 40.70880455562221,
"lng": -74.00022947934575,
"altitude": 150
},
"altitudeMode": "RELATIVE_TO_GROUND"
}
}
}
Binary file added examples/map-3d-markers/data/balloon-red.glb
Binary file not shown.
31 changes: 31 additions & 0 deletions examples/map-3d-markers/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!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: Photorealistic 3D Map with Markers</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 '@vis.gl/react-google-maps/examples.js';
import {renderToDom} from './src/app';

renderToDom(document.querySelector('#app'));
</script>
</body>
</html>
15 changes: 15 additions & 0 deletions examples/map-3d-markers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"type": "module",
"dependencies": {
"@vis.gl/react-google-maps": "latest",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"typescript": "^5.4.5",
"vite": "^6.0.11"
},
"scripts": {
"start": "vite",
"start-local": "vite --config ../vite.config.local.js",
"build": "vite build"
}
}
41 changes: 41 additions & 0 deletions examples/map-3d-markers/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import {createRoot} from 'react-dom/client';

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

import {Map3D} from './map-3d';
import ControlPanel from './control-panel';

const API_KEY =
globalThis.GOOGLE_MAPS_API_KEY ?? (process.env.GOOGLE_MAPS_API_KEY as string);

const INITIAL_VIEW_PROPS = {
center: {lat: 40.7093, lng: -73.9968, altitude: 32},
range: 1733,
heading: 5,
tilt: 70,
roll: 0
};

const App = () => {
return (
<APIProvider
apiKey={API_KEY}
version={'alpha'}
libraries={['maps3d', 'marker']}>
<Map3D {...INITIAL_VIEW_PROPS} defaultLabelsDisabled />
<ControlPanel />
</APIProvider>
);
};
export default App;

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

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

const GMP_3D_MAPS_OVERVIEW_URL =
'https://developers.google.com/maps/documentation/javascript/3d-maps-overview';

const GMP_3D_MAPS_MARKER_ADD_URL =
'https://developers.google.com/maps/documentation/javascript/3d/marker-add';

function ControlPanel() {
return (
<div className="control-panel">
<h3>3D Maps with Markers</h3>
<p>
This example implements a new <code>Map3D</code> component that renders
a 3D Globe based on the new experimental{' '}
<a href={GMP_3D_MAPS_OVERVIEW_URL} target={'_blank'}>
<code>Map3DElement</code>
</a>{' '}
web-component.
</p>

<p>
The map contains basic{' '}
<a href={GMP_3D_MAPS_MARKER_ADD_URL} target={'_blank'}>
<code>Marker3DElements</code>
</a>{' '}
as well as markers with a custom pin and a 3D model.
</p>

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

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

export default React.memo(ControlPanel);
1 change: 1 addition & 0 deletions examples/map-3d-markers/src/map-3d/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './map-3d';
51 changes: 51 additions & 0 deletions examples/map-3d-markers/src/map-3d/map-3d-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* eslint-disable @typescript-eslint/no-namespace, @typescript-eslint/no-explicit-any */

import {DOMAttributes, RefAttributes} from 'react';

// add an overload signature for the useMapsLibrary hook, so typescript
// knows what the 'maps3d' library is.
declare module '@vis.gl/react-google-maps' {
export function useMapsLibrary(
name: 'maps3d'
): typeof google.maps.maps3d | null;
}

// temporary fix until @types/google.maps is updated with the latest changes
declare global {
namespace google.maps.maps3d {
interface Map3DElement extends HTMLElement {
mode?: 'HYBRID' | 'SATELLITE';
}
}
}

// add the <gmp-map-3d> custom-element to the JSX.IntrinsicElements
// interface, so it can be used in jsx
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
['gmp-map-3d']: CustomElement<
google.maps.maps3d.Map3DElement,
google.maps.maps3d.Map3DElement
>;
}

interface IntrinsicElements {
['gmp-marker-3d']: CustomElement<
google.maps.maps3d.Marker3DElement,
google.maps.maps3d.Marker3DElement
>;
}
}
}

// a helper type for CustomElement definitions
type CustomElement<TElem, TAttr> = Partial<
TAttr &
DOMAttributes<TElem> &
RefAttributes<TElem> & {
// for whatever reason, anything else doesn't work as children
// of a custom element, so we allow `any` here
children: any;
}
>;
Loading