1. 事前準備
本程式碼研究室將說明如何使用 Maps JavaScript API 的 WebGL 技術功能,在三維向量地圖上進行控制和算繪。
必要條件
本程式碼研究室假設您已具備 JavaScript 和 Maps JavaScript API 的中階知識。如要瞭解使用 Maps JS API 的基本概念,請試試在網站中新增地圖 (JavaScript) 程式碼研究室。
課程內容
- 產生已啟用 JavaScript 專用向量地圖的地圖 ID。
- 透過程式輔助方式傾斜和旋轉地圖。
- 使用
WebGLOverlayView
和 Three.js 在地圖上算繪 3D 物件。 - 使用
moveCamera
為攝影機動作加入動畫效果。
軟硬體需求
- 已啟用計費功能的 Google Cloud Platform 帳戶
- 已啟用 Maps JavaScript API 的 Google 地圖平台 API 金鑰
- 具備 JavaScript、HTML 和 CSS 中級知識
- 您選擇的文字編輯器或 IDE
- Node.js
2. 做好準備
在下方的啟用步驟中,您需要啟用 Maps JavaScript API。
設定 Google 地圖平台
如果您尚未建立 Google Cloud Platform 帳戶,以及啟用計費功能的專案,請參閱「開始使用 Google 地圖平台」指南,建立帳單帳戶和專案。
- 在 Cloud 控制台中,按一下專案下拉式選單,然後選取要用於本程式碼研究室的專案。
- 在 Google Cloud Marketplace 中,啟用本程式碼研究室所需的 Google 地圖平台 API 和 SDK。如要瞭解如何操作,請觀看這部影片或參閱這份說明文件。
- 在 Cloud Console 的「憑證」頁面中產生 API 金鑰。你可以按照這部影片或這份文件中的步驟操作。所有 Google 地圖平台要求都需要 API 金鑰。
Node.js 設定
如果尚未安裝,請前往 https://nodejs.org/,在電腦上安裝 Node.js 執行階段。
Node.js 隨附 npm 套件管理員,您需要安裝本程式碼研究室的依附元件。
下載專案範本
開始本程式碼研究室之前,請先下載範例專案範本和完整解決方案程式碼,方法如下:
- 前往 https://github.com/googlecodelabs/maps-platform-101-webgl/,下載或建立這個程式碼研究室的 GitHub 存放區分支。範例專案位於
/starter
目錄,內含完成本程式碼研究室所需的檔案結構。所有工作所需項目都位於/starter/src
目錄中。 - 下載入門專案後,請在
/starter
目錄中執行npm install
。這會安裝package.json
中列出的所有必要依附元件。 - 安裝依附元件後,請在目錄中執行
npm start
。
我們已為您設定入門專案,方便您使用 webpack-dev-server,編譯及執行您在本機編寫的程式碼。此外,每當您變更程式碼,webpack-dev-server 也會自動在瀏覽器中重新載入應用程式。
如要查看完整的解決方案程式碼,請在 /solution
目錄中完成上述設定步驟。
新增 API 金鑰
啟動應用程式時,系統會載入地圖,並使用 JS API 載入器,因此您只需要提供 API 金鑰和地圖 ID。JS API 載入器是簡單的程式庫,可將傳統的 Maps JS API 載入方法 (使用 script
標記在 HTML 範本中內嵌載入) 抽象化,讓您在 JavaScript 程式碼中處理所有事項。
如要新增 API 金鑰,請在入門專案中執行下列操作:
- 開啟
app.js
。 - 在
apiOptions
物件中,將 API 金鑰設為apiOptions.apiKey
的值。
3. 產生及使用地圖 ID
如要使用 Maps JavaScript API 的 WebGL 功能,您需要啟用向量地圖的地圖 ID。
產生地圖 ID
- 在 Google Cloud 控制台中,依序前往「Google 地圖平台」>「地圖管理」。
- 按一下「建立新地圖 ID」。
- 在「地圖名稱」欄位中,輸入地圖 ID 的名稱。
- 在「地圖類型」下拉式選單中,選取「JavaScript」。畫面上會顯示「JavaScript 選項」。
- 在「JavaScript 選項」下方,選取「向量」單選按鈕、「傾斜」核取方塊和「旋轉」核取方塊。
- (選用) 在「說明」欄位中輸入 API 金鑰的說明。
- 按一下「下一步」按鈕。系統隨即會顯示「地圖 ID 詳細資料」頁面。
- 複製地圖 ID。您將在下一個步驟中使用此項目載入地圖。
使用地圖 ID
如要載入向量地圖,您必須在例項化地圖時,將地圖 ID 做為選項中的屬性提供。載入 Maps JavaScript API 時,您也可以選擇提供相同的地圖 ID。
如要載入含地圖 ID 的地圖,請按照下列步驟操作:
- 將地圖 ID 設為
mapOptions.mapId
的值。
執行地圖例項化時提供地圖 ID,可讓 Google 地圖平台知道要為特定例項載入哪個地圖。您可以在多個應用程式或同一個應用程式中的多個檢視畫面,重複使用相同的地圖 ID。const mapOptions = { "tilt": 0, "heading": 0, "zoom": 18, "center": { lat: 35.6594945, lng: 139.6999859 }, "mapId": "YOUR_MAP_ID" };
檢查瀏覽器中執行的應用程式。啟用傾斜和旋轉功能的向量地圖應會順利載入。如要確認是否已啟用傾斜和旋轉功能,請按住 Shift 鍵,然後使用滑鼠拖曳或使用鍵盤上的方向鍵。
如果地圖未載入,請檢查您是否已在 apiOptions
中提供有效的 API 金鑰。如果地圖無法傾斜和旋轉,請確認您提供的地圖 ID 已在 apiOptions
和 mapOptions
中啟用傾斜和旋轉功能。
您的 app.js
檔案現在看起來應像這樣:
import { Loader } from '@googlemaps/js-api-loader';
const apiOptions = {
"apiKey": 'YOUR_API_KEY',
};
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 算繪環境生命週期,供您使用。以下簡要說明各個 Hook,以及適用的用途:
onAdd()
:在WebGLOverlayView
執行個體上呼叫setMap
,將疊加層加到地圖時呼叫。您應在此處執行任何與 WebGL 相關的工作,不需要直接存取 WebGL 環境。onContextRestored()
:在 WebGL 環境可用時呼叫,但會在任何內容算繪前呼叫。您應在此初始化物件、繫結狀態,以及執行任何需要存取 WebGL 環境,但可在onDraw()
呼叫之外執行的作業。這樣一來,您就能設定所需的一切,而不會為地圖的實際算繪作業增加過多負擔,因為這項作業本來就很耗用 GPU 資源。onDraw()
:WebGL 開始算繪地圖和您要求的任何其他內容時,每個影格都會呼叫一次這個函式。您應盡量減少onDraw()
中的工作,避免地圖算繪發生效能問題。onContextLost()
:如有任何因素造成 WebGL 算繪環境遺失,系統會呼叫這個方法。onRemove()
:在WebGLOverlayView
執行個體上呼叫setMap(null)
,從地圖中移除疊加層時,系統會呼叫這個方法。
在這個步驟中,您將建立 WebGLOverlayView
的執行個體,並實作三個生命週期掛鉤:onAdd
、onContextRestored
和 onDraw
。為確保程式碼乾淨整潔且易於追蹤,所有疊加層的程式碼都會在 initWebGLOverlayView()
函式中處理,這個函式是本程式碼研究室入門範本提供的函式。
- 建立
WebGLOverlayView()
執行個體。
疊加層是由 Maps JS API 在google.maps.WebGLOverlayView
中提供。首先,請將下列內容附加至initWebGLOverlayView()
,建立例項:const webGLOverlayView = new google.maps.WebGLOverlayView();
- 實作生命週期掛鉤。
如要實作生命週期掛鉤,請將下列內容附加至initWebGLOverlayView()
:webGLOverlayView.onAdd = () => {}; webGLOverlayView.onContextRestored = ({gl}) => {}; webGLOverlayView.onDraw = ({gl, transformer}) => {};
- 將疊加層例項加到地圖。
現在請在疊加層例項上呼叫setMap()
,並將地圖傳遞至initWebGLOverlayView()
,方法是在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, transformer}) => {}
webGLOverlayView.setMap(map);
}
(async () => {
const map = await initMap();
initWebGLOverlayView(map);
})();
這樣就完成 WebGLOverlayView
的實作作業。接著,您將設定使用 Three.js 在地圖上算繪 3D 物件所需的一切。
5. 設定 three.js 場景
使用 WebGL 可能非常複雜,因為您必須手動定義每個物件的所有層面,以及其他一些項目。為了簡化操作,本程式碼研究室將使用 Three.js,這是熱門的圖形程式庫,可在 WebGL 上提供簡化的抽象層。Three.js 隨附各種便利函式,可執行從建立 WebGL 轉譯器到繪製常見 2D 和 3D 物件形狀,以及控制攝影機、物件轉換等各種作業。
Three.js 中有三種基本物件類型,顯示任何內容都必須使用這些類型:
- 場景:所有物件、光源、紋理等項目都會在這個「容器」中算繪及顯示。
- 攝影機:代表場景視角的攝影機。你可以使用多種攝影機類型,並在單一場景中新增一或多部攝影機。
- 算繪器:處理及顯示場景中所有物件的算繪器。在 Three.js 中,
WebGLRenderer
是最常用的,但如果用戶端不支援 WebGL,您也可以使用其他幾種做為備援。
在這個步驟中,您會載入 Three.js 所需的所有依附元件,並設定基本場景。
- 載入 three.js
本程式碼研究室需要兩個依附元件:Three.js 程式庫和 GLTF Loader,這個類別可讓您載入 GL 傳輸格式 (gLTF) 的 3D 物件。Three.js 提供許多不同 3D 物件格式的專用載入器,但建議使用 gLTF。
在下列程式碼中,系統會匯入整個 Three.js 程式庫。在正式版應用程式中,您可能只想匯入所需的類別,但在本程式碼研究室中,請匯入整個程式庫,讓操作更簡單。另請注意,GLTF Loader 不會納入預設程式庫,必須從依附元件中的個別路徑匯入,您可透過這個路徑存取 Three.js 提供的所有載入器。
如要匯入 Three.js 和 GLTF Loader,請在app.js
頂端新增下列內容:import * as THREE from 'three'; import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js';
- 建立 three.js 場景。
如要建立場景,請將下列內容附加至onAdd
hook,例項化 Three.jsScene
類別:scene = new THREE.Scene();
- 在場景中新增攝影機。
如先前所述,相機代表場景的觀看角度,並決定 Three.js 如何處理場景中物件的視覺化算繪作業。如果沒有攝影機,系統就無法「看到」場景,因此不會轉譯物件,物件也不會顯示。
Three.js 提供各種不同的攝影機,可影響算繪器處理物件的方式,例如透視和深度。在這個場景中,您將使用PerspectiveCamera
,這是 Three.js 中最常用的攝影機類型,旨在模擬人眼感知場景的方式。也就是說,離相機越遠的物體會越小,場景會有消失點等等。
如要將透視攝影機新增至場景,請在onAdd
勾點後方加上以下內容: 您也可以使用camera = new THREE.PerspectiveCamera();
PerspectiveCamera
設定構成視點的屬性,包括近平面和遠平面、長寬比和視野 (fov)。這些屬性共同構成所謂的檢視截錐體,這是處理 3D 時的重要概念,但超出本程式碼研究室的範圍。預設的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 Canvas 的 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
Hook:renderer = new THREE.WebGLRenderer({ canvas: gl.canvas, context: gl, ...gl.getContextAttributes(), }); renderer.autoClear = false;
- 算繪場景。
設定好算繪器後,請在WebGLOverlayView
執行個體上呼叫requestRedraw
,告知疊加層在算繪下一個影格時需要重新繪製,然後在算繪器上呼叫render
,並傳遞要算繪的 Three.js 場景和攝影機。最後,請清除 WebGL 算繪環境的狀態。這是避免 GL 狀態衝突的重要步驟,因為使用 WebGL Overlay View 時,會用到共用的 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 Loader。
3D 模型有許多不同格式,但就 Three.js 而言,gLTF 格式是首選格式,因為其大小和執行階段效能都相當出色。在本程式碼研究室中,/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
回呼中,加入以下內容scene.add(gltf.scene)
,將 gLTF 新增至場景: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 圖釘:
您學到的內容
在本程式碼研究室中,您學到許多內容,以下是重點:
- 實作
WebGLOverlayView
及其生命週期掛鉤。 - 將 Three.js 整合到地圖中。
- 建立 Three.js 場景的基本知識,包括攝影機和照明。
- 使用 Three.js 載入及操控 3D 模型。
- 使用
moveCamera
控制地圖的攝影機並製作動畫。
後續步驟
WebGL 和一般電腦繪圖都是複雜的主題,因此總有許多內容可供學習。以下資源可協助您快速上手:
- WebGL 疊加層檢視說明文件
- 開始使用 WebGL。
- Three.js 說明文件
- 請回答下列問題,協助我們製作您認為最有用的內容:「codelabs/maps-platform/shared/_next-lab-survey.lab.md」您想要的程式碼研究室未列於上方嗎?請在這裡提出新的問題。