-
Notifications
You must be signed in to change notification settings - Fork 822
/
index.ts
135 lines (115 loc) · 3.77 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* @license
* Copyright 2021 Google LLC.
* SPDX-License-Identifier: Apache-2.0
*/
// [START maps_webgl_overlay_simple]
// [START maps_webgl_overlay_simple_init_map]
import {
AmbientLight,
DirectionalLight,
Matrix4,
PerspectiveCamera,
Scene,
WebGLRenderer,
} from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
let map: google.maps.Map;
const mapOptions = {
tilt: 0,
heading: 0,
zoom: 18,
center: { lat: 35.6594945, lng: 139.6999859 },
mapId: "15431d2b469f209e",
// disable interactions due to animation loop and moveCamera
disableDefaultUI: true,
gestureHandling: "none",
keyboardShortcuts: false,
};
function initMap(): void {
const mapDiv = document.getElementById("map") as HTMLElement;
map = new google.maps.Map(mapDiv, mapOptions);
initWebglOverlayView(map);
}
// [END maps_webgl_overlay_simple_init_map]
// [START maps_webgl_overlay_simple_on_add]
function initWebglOverlayView(map: google.maps.Map): void {
let scene, renderer, camera, loader;
const webglOverlayView = new google.maps.WebGLOverlayView();
webglOverlayView.onAdd = () => {
// Set up the scene.
scene = new Scene();
camera = new PerspectiveCamera();
const ambientLight = new AmbientLight(0xffffff, 0.75); // Soft white light.
scene.add(ambientLight);
const directionalLight = new DirectionalLight(0xffffff, 0.25);
directionalLight.position.set(0.5, -1, 0.5);
scene.add(directionalLight);
// Load the model.
loader = new GLTFLoader();
const source =
"https://raw.githubusercontent.com/googlemaps/js-samples/main/assets/pin.gltf";
loader.load(source, (gltf) => {
gltf.scene.scale.set(10, 10, 10);
gltf.scene.rotation.x = Math.PI; // Rotations are in radians.
scene.add(gltf.scene);
});
};
// [END maps_webgl_overlay_simple_on_add]
// [START maps_webgl_overlay_simple_on_context_restored]
webglOverlayView.onContextRestored = ({ gl }) => {
// Create the js renderer, using the
// maps's WebGL rendering context.
renderer = new WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
// Wait to move the camera until the 3D model loads.
loader.manager.onLoad = () => {
renderer.setAnimationLoop(() => {
webglOverlayView.requestRedraw();
const { tilt, heading, zoom } = mapOptions;
map.moveCamera({ tilt, heading, zoom });
// Rotate the map 360 degrees.
if (mapOptions.tilt < 67.5) {
mapOptions.tilt += 0.5;
} else if (mapOptions.heading <= 360) {
mapOptions.heading += 0.2;
mapOptions.zoom -= 0.0005;
} else {
renderer.setAnimationLoop(null);
}
});
};
};
// [END maps_webgl_overlay_simple_on_context_restored]
// [START maps_webgl_overlay_simple_on_draw]
webglOverlayView.onDraw = ({ gl, transformer }): void => {
const latLngAltitudeLiteral: google.maps.LatLngAltitudeLiteral = {
lat: mapOptions.center.lat,
lng: mapOptions.center.lng,
altitude: 100,
};
// Update camera matrix to ensure the model is georeferenced correctly on the map.
const matrix = transformer.fromLatLngAltitude(latLngAltitudeLiteral);
camera.projectionMatrix = new Matrix4().fromArray(matrix);
webglOverlayView.requestRedraw();
renderer.render(scene, camera);
// Sometimes it is necessary to reset the GL state.
renderer.resetState();
};
// [END maps_webgl_overlay_simple_on_draw]
// [START maps_webgl_overlay_simple_add_to_map]
webglOverlayView.setMap(map);
// [END maps_webgl_overlay_simple_add_to_map]
}
declare global {
interface Window {
initMap: () => void;
}
}
window.initMap = initMap;
// [END maps_webgl_overlay_simple]
export {};