1. 准备工作
此 Codelab 会教您如何使用由 WebGL 提供支持的 Maps JavaScript API 功能控制三维矢量地图并在地图上渲染对象。
前提条件
此 Codelab 假定您熟悉 JavaScript 和 Maps JavaScript API 方面的知识。如需了解使用 Maps JS API 的基础知识,不妨试着学习向网站添加地图 (JavaScript) Codelab。
学习内容
- 生成地图 ID,并启用支持 JavaScript 的矢量地图。
- 通过程序化的倾斜和旋转控制地图。
- 使用
WebGLOverlayView
和 Three.js 在地图上渲染 3D 对象。 - 使用
moveCamera
呈现相机移动动画。
所需条件
- 已启用结算功能的 Google Cloud Platform 帐号
- 已启用 Maps JavaScript API 的 Google Maps Platform API 密钥
- 熟悉 JavaScript、HTML 和 CSS 方面的知识
- 您自己喜欢用的文本编辑器或 IDE
- Node.js
2. 进行设置
若要完成下面的启用步骤,您需要启用 Maps JavaScript API。
设置 Google Maps Platform
如果您还没有已启用结算功能的 Google Cloud Platform 帐号和项目,请参阅 Google Maps Platform 使用入门指南,创建结算帐号和项目。
- 在 Cloud Console 中,点击项目下拉菜单,选择要用于此 Codelab 的项目。
- 在 Google Cloud Marketplace 中启用此 Codelab 所需的 Google Maps Platform API 和 SDK。为此,请按照此视频或此文档中的步骤操作。
- 在 Cloud Console 的凭据页面中生成 API 密钥。您可以按照此视频或此文档中的步骤操作。必须要有 API 密钥才能向 Google Maps Platform 发送请求。
Node.js 设置
如果您还没有 Node.js,请转到 https://nodejs.org/,在计算机上下载并安装 Node.js 运行时。
Node.js 附带 npm 软件包管理器,您可以借此安装此 Codelab 的依赖项。
下载项目入门模板
在开始此 Codelab 之前,请按照下列步骤下载入门项目模板以及完整的解决方案代码:
- 请访问 https://github.com/googlecodelabs/maps-platform-101-webgl/,下载此 Codelab 的 GitHub 代码库或创建分支。入门项目位于
/starter
目录,其中包含完成此 Codelab 所需的基本文件结构。您需要的所有内容均位于/starter/src
目录中。 - 下载入门项目后,请运行
/starter
目录中的npm install
。此操作会安装package.json
中列出的所有必需依赖项。 - 安装依赖项后,请运行目录中的
npm start
。
入门项目已设置完毕,您可以使用 webpack-dev-server 编译并运行您在本地编写的代码。webpack-dev-server 还会在您更改代码时自动在浏览器中重新加载您的应用。
如果您希望运行完整的解决方案代码,请在 /solution
目录中完成上述设置步骤。
添加您的 API 密钥
入门应用包含通过 JS API 加载器加载地图所需的所有代码,因此您只需提供 API 密钥和地图 ID 即可。JS API 加载器是一个简单的库,它将在 HTML 模板中使用 script
标记内联加载 Maps JS API 的传统方式抽象化,让您可以通过 JavaScript 代码处理所有内容。
若要添加 API 密钥,请在入门项目中执行以下操作:
- 打开
app.js
。 - 在
apiOptions
对象中,将您的 API 密钥设为apiOptions.apiKey
的值。
3. 生成和使用地图 ID
若要使用基于 WebGL 的 Maps JavaScript API 功能,您需要一个地图 ID,还要启用矢量地图。
生成地图 ID
- 在 Google Cloud Console 中,转到“Google Maps Platform”,然后进入“地图管理”。
- 点击“创建新的地图 ID”。
- 在“地图名称”字段中,输入地图 ID 的名称。
- 在“地图类型”下拉菜单中,选择“JavaScript”。此时将显示“JavaScript Options”(JavaScript 选项)。
- 在“JavaScript Options”(JavaScript 选项)下,选中“矢量”单选按钮、“倾斜”复选框和“旋转”复选框。
- 可选项。在“说明”字段中,输入 API 密钥的说明。
- 点击“下一步”按钮。此时会显示“地图 ID 详情”页面。
- 复制地图 ID。您将在下一步中使用该 ID 来加载地图。
使用地图 ID
若要加载矢量地图,您必须在实例化地图时在相应选项中提供地图 ID 作为属性。或者,您也可以在加载 Maps JavaScript API 时提供相同的地图 ID。
若要使用地图 ID 加载地图,请执行以下操作:
- 将您的地图 ID 设为
mapOptions.mapId
的值。
在实例化地图时提供地图 ID 可告知 Google Maps Platform 针对特定实例加载哪些地图。您可以跨多个应用或同一应用内的多个视图重复使用同一个地图 ID。const mapOptions = { "tilt": 0, "heading": 0, "zoom": 18, "center": { lat: 35.6594945, lng: 139.6999859 }, "mapId": "YOUR_MAP_ID" };
检查在浏览器中运行的应用。启用了倾斜和旋转的矢量地图应该可以成功加载。若要检查倾斜和旋转是否已启用,请按住 Shift 键,并使用鼠标拖动或使用键盘上的箭头键。
如果地图未加载,请检查您是否已在 apiOptions
中提供有效的 API 密钥。如果地图未倾斜和旋转,请检查您是否已在 apiOptions
和 mapOptions
中提供地图 ID 并启用倾斜和旋转。
您的 app.js
文件现在应如下所示:
import { Loader } from '@googlemaps/js-api-loader';
const apiOptions = {
"apiKey": 'YOUR_API_KEY',
"version": "beta"
};
const mapOptions = {
"tilt": 0,
"heading": 0,
"zoom": 18,
"center": { lat: 35.6594945, lng: 139.6999859 },
"mapId": "YOUR_MAP_ID"
}
async function initMap() {
const mapDiv = document.getElementById("map");
const apiLoader = new Loader(apiOptions);
await apiLoader.load();
return new google.maps.Map(mapDiv, mapOptions);
}
function initWebGLOverlayView (map) {
let scene, renderer, camera, loader;
// WebGLOverlayView code goes here
}
(async () => {
const map = await initMap();
})();
4. 实现 WebGLOverlayView
借助 WebGLOverlayView
,您可以直接访问用于渲染矢量基本地图的相同 WebGL 渲染上下文。也就是说,您可以使用 WebGL 以及基于 WebGL 的热门图形库直接在地图上渲染 2D 和 3D 对象。
WebGLOverlayView
提供五个钩子,您可以在地图的 WebGL 渲染上下文的生命周期中使用它们。以下是每个钩子的简要说明及其用途:
onAdd()
:在对WebGLOverlayView
实例调用setMap
以将叠加层添加到地图时调用。您应在此处执行与 WebGL 相关但不需要直接访问 WebGL 上下文的任何操作。onContextRestored()
:在 WebGL 上下文可用且未渲染任何内容之前调用。您应在此处初始化对象、绑定状态,并执行需要访问 WebGL 上下文但无需调用onDraw()
的其他任何操作。这样一来,您就可以完成所需的全部设置,而不用增加地图的实际渲染开销,地图本身已经占用大量 GPU 资源。onDraw()
:在 WebGL 开始渲染地图以及您请求的其他内容后,每帧调用一次。您应尽可能减少在onDraw()
中的操作,以免地图渲染出现性能问题。onContextLost()
:在 WebGL 渲染上下文因任何原因丢失时调用。onRemove()
:在WebGLOverlayView
实例上调用setMap(null)
以从地图中移除叠加层时调用。
在此步骤中,您将创建 WebGLOverlayView
实例,并实现三个生命周期钩子:onAdd
、onContextRestored
和 onDraw
。为了确保内容简洁且易于理解,叠加层的所有代码都将通过此 Codelab 入门模板中提供的 initWebGLOverlayView()
函数进行处理。
- 创建
WebGLOverlayView()
实例。
叠加层由 Maps JS API 在google.maps.WebGLOverlayView
中提供。首先,通过将以下代码附加到initWebGLOverlayView()
来创建一个实例:const webGLOverlayView = new google.maps.WebGLOverlayView();
- 实现生命周期钩子。
若要实现生命周期钩子,请将以下代码附加到initWebGLOverlayView()
:webGLOverlayView.onAdd = () => {}; webGLOverlayView.onContextRestored = ({gl}) => {}; webGLOverlayView.onDraw = ({gl, coordinateTransformer}) => {};
- 向地图添加叠加层实例。
现在,在叠加层实例上调用setMap()
,并将以下代码附加到initWebGLOverlayView()
以传入地图:webGLOverlayView.setMap(map)
- 调用
initWebGLOverlayView
。
最后一步是执行initWebGLOverlayView()
,将以下代码添加到app.js
底部立即调用的函数中即可:initWebGLOverlayView(map);
您的 initWebGLOverlayView
和立即调用的函数现在应如下所示:
async function initWebGLOverlayView (map) {
let scene, renderer, camera, loader;
const webGLOverlayView = new google.maps.WebGLOverlayView();
webGLOverlayView.onAdd = () => {}
webGLOverlayView.onContextRestored = ({gl}) => {}
webGLOverlayView.onDraw = ({gl, coordinateTransformer}) => {}
webGLOverlayView.setMap(map);
}
(async () => {
const map = await initMap();
initWebGLOverlayView(map);
})();
以上就是实现 WebGLOverlayView
的所有步骤。接下来,您将使用 Three.js 完成在地图上渲染 3D 对象所需的全部设置。
5. 设置 Three.js 场景
使用 WebGL 可能会非常复杂,因为您需要手动定义每个对象的各个方面,还要注意其他事项。为了简化操作,此 Codelab 中将使用 Three.js,这个一个热门的图形库,可在 WebGL 上提供简化的抽象层。Three.js 附带多种便捷函数,可用于处理各种任务,例如创建 WebGL 渲染程序、绘制常见的 2D 和 3D 对象形状、控制相机和对象转换等。
Three.js 中有以下三种基本的对象类型,它们是显示内容的必要条件:
- 场景:“容器”,所有对象、光源及纹理等内容的渲染和显示都在其中完成。
- 相机:代表场景视角的相机。有多种相机类型可供选择,可以为一个场景添加一个或多个相机。
- 渲染程序:用于处理和显示场景中所有对象的渲染程序。
WebGLRenderer
是 Three.js 中最常用的渲染程序,但在客户端不支持 WebGL 的情况下,可以将其他一些渲染程序作为备用。
在此步骤中,您将加载 Three.js 所需的所有依赖项,并设置基本场景。
- 加载 Three.js
在此 Codelab 中,您需要两个依赖项:Three.js 库和 GLTF 加载器,后者是一个可让您以 GL 传输格式 (gLTF) 加载 3D 对象的类。Three.js 为许多不同的 3D 对象格式提供了专用加载器,但建议使用 gLTF。
在下面的代码中,导入了整个 Three.js 库。在正式版应用中,您可能只需要导入所需的类,但对于此 Codelab,导入整个库是为了简化操作。另请注意,GLTF 加载器未包含在默认库中,需要从依赖项中的单独路径导入,您可以通过此路径访问 Three.js 提供的所有加载器。
若要导入 Three.js 和 GLTF 加载器,请将以下代码添加到app.js
的顶部:import * as THREE from 'three'; import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js';
- 创建一个 Three.js 场景。
若要创建场景,请将以下代码附加到onAdd
钩子,以实例化 Three.jsScene
类:scene = new THREE.Scene();
- 向场景添加相机。
如前所述,相机代表场景的视角,并决定 Three.js 如何处理场景中对象的视觉渲染。如果没有相机,场景实际上就不会被“看到”,这意味着对象不会显示,因为它们没有被渲染。
Three.js 提供了各种不同的相机,这些相机会影响渲染程序处理对象的方式,比如视角和深度。在此场景中,您将使用PerspectiveCamera
,这是 Three.js 中最常用的相机类型,旨在模拟人眼感知场景的方式。也就是说,离相机较远的对象看起来比离得较近的要小,场景中会有一个消失点,类似特点还有很多。
若要向场景添加透视相机,请将以下代码附加到onAdd
钩子:
借助camera = new THREE.PerspectiveCamera();
PerspectiveCamera
,您还能够配置构成视角的属性,包括近平面和远平面、宽高比和视野 (fov)。这些属性共同构成了所谓的视锥体,这是处理 3D 对象时务必要理解的一个概念,但不在此 Codelab 的范围内。默认的PerspectiveCamera
配置足以满足需求。 - 向场景添加光源。
默认情况下,在 Three.js 场景中渲染的对象将显示为黑色,无论它们应用何种纹理都是如此。这是因为 Three.js 场景会模仿对象在现实世界中的呈现方式,其中颜色取决于对象反射的光线。简而言之,没有光,就没有颜色。
Three.js 提供了各种不同类型的光源,您将使用其中两种: AmbientLight
:提供漫射光源,可从各个角度均匀地照射场景中的所有对象。这将为场景提供基础亮度,确保所有对象的纹理都可呈现出来。DirectionalLight
:沿着场景中的某个方向发出光线。与现实世界中定位光的原理不同,DirectionalLight
发出的光线都是平行的,不会随着远离光源而扩散和漫射。
您可以配置每个光线的颜色和强度,以创造整体的光线效果。例如,在下面的代码中,环境光为整个场景提供柔和的白光,而平行光作为辅助光向下照射对象。对于平行光,应使用position.set(x, y ,z)
设置角度,其中每个值都对应各自的轴。例如,设为position.set(0,1,0)
时,光线会从场景正上方沿着 y 轴直射下来。
若要向场景添加光源,请将以下代码附加到onAdd
钩子:const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.25); directionalLight.position.set(0.5, -1, 0.5); scene.add(directionalLight);
您的 onAdd
钩子现在应如下所示:
webGLOverlayView.onAdd = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 );
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.25);
directionalLight.position.set(0.5, -1, 0.5);
scene.add(directionalLight);
}
您的场景现已设置完毕,可以开始渲染了。接下来,您将配置 WebGL 渲染程序,并渲染场景。
6. 渲染场景
我们现在开始渲染场景。到目前为止,您使用 Three.js 创建的所有内容都已在代码中进行初始化,但实际上并不存在,因为它尚未渲染到 WebGL 渲染上下文中。WebGL 使用 Canvas API 在浏览器中渲染 2D 和 3D 内容。如果您之前使用过 Canvas API,应该熟悉 HTML 画布的 context
,这是渲染所有内容的地方。您可能不知道,它是一个通过 WebGLRenderingContext
API 在浏览器中公开 OpenGL 图形渲染上下文的接口。
为了更轻松地处理 WebGL 渲染程序,Three.js 提供了 WebGLRenderer
,这是一个封装容器,可相对轻松地配置 WebGL 渲染上下文,让 Three.js 在浏览器中渲染场景。但对于地图而言,仅在浏览器中与地图一起渲染 Three.js 场景是不够的。Three.js 场景必须渲染到与地图完全相同的渲染上下文中,以便地图和 Three.js 场景中的任何对象都渲染到相同的世界空间中。这样一来,渲染程序就可以处理地图上对象与场景中对象之间的互动(例如遮挡),换一种说法就是某个对象会遮住它后面的对象,让人看不到它们。
听起来很复杂,对吧?幸运的是,仍然可以通过 Three.js 简化操作。
- 设置 WebGL 渲染程序。
当您创建 Three.jsWebGLRenderer
新实例时,可以为其提供您希望用于渲染场景的特定 WebGL 渲染上下文。还记得传递到onContextRestored
钩子的gl
参数吗?该gl
对象就是地图的 WebGL 渲染上下文。您只需向WebGLRenderer
实例提供上下文、画布及属性,所有这些内容均可通过gl
对象获得。在下面的代码中,渲染程序的autoClear
属性也设为false
,这样渲染程序就不会在每一帧都清除其输出。
若要配置渲染程序,请将以下代码附加到onContextRestored
钩子:renderer = new THREE.WebGLRenderer({ canvas: gl.canvas, context: gl, ...gl.getContextAttributes(), }); renderer.autoClear = false;
- 渲染场景。
渲染程序配置完毕后,在WebGLOverlayView
实例上调用requestRedraw
,以告知叠加层在渲染下一帧时需要重新绘制,然后在渲染程序上调用render
并向其传递 Three.js 场景和相机,以进行渲染。最后,清除 WebGL 渲染上下文的状态。这一步对于避免 GL 状态冲突至关重要,因为 WebGL 叠加视图的使用依赖于共享的 GL 状态。如果每次绘制调用结束时都未重置状态,GL 状态冲突可能会导致渲染程序出现问题。
为此,请将以下代码附加到onDraw
钩子,以便在每一帧渲染结束时重置状态:webGLOverlayView.requestRedraw(); renderer.render(scene, camera); renderer.resetState();
您的 onContextRestored
和 onDraw
钩子现在应如下所示:
webGLOverlayView.onContextRestored = ({gl}) => {
renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
}
webGLOverlayView.onDraw = ({gl, transformer}) => {
webGLOverlayView.requestRedraw();
renderer.render(scene, camera);
renderer.resetState();
}
7. 在地图上渲染 3D 模型
好了,您已经完成所有准备工作。您设置了 WebGL 叠加视图,创建了 Three.js 场景,但有一个问题:场景中没有任何内容。接下来,我们开始在场景中渲染 3D 对象。为此,您将使用之前导入的 GLTF 加载器。
3D 模型具有多种不同格式,但考虑到 Three.js 场景的大小和运行时性能,gLTF 是首选格式。在此 Codelab 中,/src/pin.gltf
中已经提供一个可用于在场景中进行渲染的模型。
- 创建模型加载器实例。
将以下代码附加到onAdd
:loader = new GLTFLoader();
- 加载 3D 模型。
模型加载器是异步的,并会在模型完全加载后执行回调。若要加载pin.gltf
,请将以下代码附加到onAdd
:const source = "pin.gltf"; loader.load( source, gltf => {} );
- 向场景添加模型。
现在,您可以将以下代码附加到loader
回调,以向场景添加模型。请注意,要添加的是gltf.scene
,而不是gltf
:scene.add(gltf.scene);
- 配置相机投影矩阵。
为了在地图上正确渲染模型,最后一步是在 Three.js 场景中设置相机的投影矩阵。投影矩阵通过 Three.jsMatrix4
数组的形式指定,数组可以定义三维空间中的一个点以及转换(例如旋转、剪切和缩放)。
对于WebGLOverlayView
,投影矩阵可用于告知渲染程序相对于基本地图的位置以及如何渲染 Three.js 场景。但有一个问题,地图上的位置通过纬度和经度坐标对的形式指定,而 Three.js 场景中的位置则采用Vector3
坐标。您可能已经猜到,计算两个坐标系统之间的转换并非易事。为了解决此问题,WebGLOverlayView
会将coordinateTransformer
对象传递到OnDraw
生命周期钩子(其中包含名为fromLatLngAltitude
的函数)。fromLatLngAltitude
采用LatLngAltitude
或LatLngAltitudeLiteral
对象,以及一组可为场景定义转换的参数(视情况而定),然后将它们转换为模型视图投影 (MVP) 矩阵。您只需指定 Three.js 场景在地图上的渲染位置以及转换方式,WebGLOverlayView
将完成剩余的工作。然后,您可以将 MVP 矩阵转换为 Three.jsMatrix4
数组,并为其设置相机投影矩阵。
在下面的代码中,第二个参数告知 WebGL 叠加视图将 Three.js 场景的海拔高度设为离地面 120 米,这会让模型看起来像是悬浮在空中。
若要设置相机投影矩阵,请将以下代码附加到onDraw
钩子:const latLngAltitudeLiteral = { lat: mapOptions.center.lat, lng: mapOptions.center.lng, altitude: 120 } const matrix = transformer.fromLatLngAltitude(latLngAltitudeLiteral); camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
- 转换模型。
您会发现图钉并没有垂直于地图。在 3D 图形中,除了世界空间拥有自己的 x 轴、y 轴和 z 轴(用于确定方向)之外,每个对象也有自己的对象空间和一组独立的轴。
对此模型而言,图钉“顶部”通常不会沿着 y 轴朝上,因此您需要通过对其调用rotation.set
来转换对象,以便获得相对于世界空间的正确方向。请注意,在 Three.js 中,旋转的单位是弧度,而不是角度。通常情况下,使用角度会更方便,因此需要使用公式degrees * Math.PI/180
进行适当的转换。
此外,这个模型有点小,因此您还可以调用scale.set(x, y ,z)
,以便在所有轴上均匀缩放该模型。
若要旋转和缩放模型,请将以下代码添加到onAdd
的loader
回调,并将其放在用于将向场景添加 gLTF 的scene.add(gltf.scene)
之前:gltf.scene.scale.set(25,25,25); gltf.scene.rotation.x = 180 * Math.PI/180;
现在,图钉垂直于地图。
您的 onAdd
和 onDraw
钩子现在应如下所示:
webGLOverlayView.onAdd = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // soft white light
scene.add( ambientLight );
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.25);
directionalLight.position.set(0.5, -1, 0.5);
scene.add(directionalLight);
loader = new GLTFLoader();
const source = 'pin.gltf';
loader.load(
source,
gltf => {
gltf.scene.scale.set(25,25,25);
gltf.scene.rotation.x = 180 * Math.PI/180;
scene.add(gltf.scene);
}
);
}
webGLOverlayView.onDraw = ({gl, transformer}) => {
const latLngAltitudeLiteral = {
lat: mapOptions.center.lat,
lng: mapOptions.center.lng,
altitude: 100
}
const matrix = transformer.fromLatLngAltitude(latLngAltitudeLiteral);
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
webGLOverlayView.requestRedraw();
renderer.render(scene, camera);
renderer.resetState();
}
接下来是相机动画!
8. 呈现相机移动动画
现在,您已经在地图上渲染了一个模型,可以通过三个维度移动任何对象,接下来可能需要以编程方式控制这种移动。借助 moveCamera
函数,您可以同时设置地图的中心、缩放、倾斜和方向属性,从而精细控制用户体验。此外,可在动画循环中调用 moveCamera
,以接近每秒 60 帧的帧速率在帧之间打造流畅的过渡。
- 等待模型加载。
为了打造顺畅的用户体验,您需要在 gLTF 模型加载完毕后再开始移动相机。为此,请将加载器的onLoad
事件处理脚本附加到onContextRestored
钩子:loader.manager.onLoad = () => {}
- 创建动画循环。
动画循环创建方式有很多,例如使用setInterval
或requestAnimationFrame
。在本示例中,您将使用 Three.js 渲染程序的setAnimationLoop
函数,该函数会在 Three.js 每次渲染新帧时自动调用您在其回调中声明的任何代码。若要创建动画循环,请将以下代码添加到上一步的onLoad
事件处理脚本:renderer.setAnimationLoop(() => {});
- 设置相机在动画循环中的位置。
接下来,调用moveCamera
以更新地图。在这里,用于加载地图的mapOptions
对象中的属性用于定义相机位置:map.moveCamera({ "tilt": mapOptions.tilt, "heading": mapOptions.heading, "zoom": mapOptions.zoom });
- 逐帧更新相机。
最后一步!在每一帧结束时更新mapOptions
对象,以设置下一帧的相机位置。在下面的代码中,if
语句用于增加倾斜度,直至达到最大倾斜值 67.5,每帧的方向都略有变动,直至相机完成完整的 360 度旋转。达到理想动画效果后,系统会将null
传递给setAnimationLoop
以取消动画,使其不会永久运行。if (mapOptions.tilt < 67.5) { mapOptions.tilt += 0.5 } else if (mapOptions.heading <= 360) { mapOptions.heading += 0.2; } else { renderer.setAnimationLoop(null) }
您的 onContextRestored
钩子现在应如下所示:
webGLOverlayView.onContextRestored = ({gl}) => {
renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
loader.manager.onLoad = () => {
renderer.setAnimationLoop(() => {
map.moveCamera({
"tilt": mapOptions.tilt,
"heading": mapOptions.heading,
"zoom": mapOptions.zoom
});
if (mapOptions.tilt < 67.5) {
mapOptions.tilt += 0.5
} else if (mapOptions.heading <= 360) {
mapOptions.heading += 0.2;
} else {
renderer.setAnimationLoop(null)
}
});
}
}
9. 恭喜
如果一切按计划进行,您现在应该可以看到一个带有较大 3D 图钉的地图,如下所示:
所学内容
您在此 Codelab 中学习了许多知识;重点内容如下:
- 实现
WebGLOverlayView
及其生命周期钩子。 - 将 Three.js 集成到地图中。
- 创建 Three.js 场景的基础知识,包括相机和光线。
- 使用 Three.js 加载和操控 3D 模型。
- 使用
moveCamera
控制地图的相机,并呈现相机移动动画效果。
后续内容
一般来说,WebGL 和计算机图形是比较复杂的主题,因此总有许多内容需要学习。以下是一些可帮助您开始学习的资源:
- WebGL 叠加视图文档
- WebGL 使用入门
- Three.js 文档
- 请回答下面的问题,帮助我们制作您认为最实用的内容:«codelabs/maps-platform/shared/_next-lab-survey.lab.md» 上面没有列出您希望了解的 Codelab?没关系,请在此处通过创建新问题的方式申请 Codelab。