您可以透過 WebGL 疊加層檢視,直接使用 WebGL 或常用圖形程式庫 (例如 Three.js) 在地圖上新增內容。運用 WebGL 疊加層檢視,即可直接存取 Google 地圖平台算繪向量基本地圖的環境。共用算繪環境有許多好處,包括運用 3D 建築物幾何圖形進行深度遮蔽,及同步處理 2D/3D 內容與基本地圖算繪。透過 WebGL 疊加層檢視算繪的物件也可以與經緯度座標建立關聯,因此當您拖曳、縮放、平移或傾斜地圖時,這些物件會隨之移動。
需求條件
如要使用 WebGL 疊加層檢視,請透過已啟用向量地圖的地圖 ID 載入地圖。強烈建議您在建立地圖 ID 時啟用傾斜和旋轉,即可使用完整的 3D 攝影機控制功能。詳情請參閱總覽。
新增 WebGL 疊加層檢視
如要將疊加層加入地圖,請導入 google.maps.WebGLOverlayView
,然後使用 setMap
傳遞至地圖執行個體:
// Create a map instance.
const map = new google.maps.Map(mapDiv, mapOptions);
// Create a WebGL Overlay View instance.
const webglOverlayView = new google.maps.WebGLOverlayView();
// Add the overlay to the map.
webglOverlayView.setMap(map);
生命週期掛鉤
WebGL 疊加層檢視提供一組掛鉤,可在向量基本地圖 WebGL 算繪環境生命週期中的不同時間點呼叫。在這些生命週期掛鉤中,您可以設定、繪製及拆解要在疊加層中算繪的任何內容。
- 建立疊加層後,系統會呼叫
onAdd()
。在繪製疊加層前,請使用此方法擷取或建立中繼資料結構,不需要立即存取 WebGL 算繪環境。 - 算繪環境可供使用時,系統會呼叫
onContextRestored({gl})
。可用來初始化或繫結任何 WebGL 狀態,例如著色器、GL 緩衝區物件等。onContextRestored()
會採用WebGLStateOptions
執行個體,其中包含單一欄位:gl
是基本地圖使用的WebGLRenderingContext
控制代碼。
onDraw({gl, transformer})
會在基本地圖上算繪場景。onDraw()
的參數是WebGLDrawOptions
物件,其中包含兩個欄位:gl
是基本地圖使用的WebGLRenderingContext
控制代碼。transformer
提供輔助函式,能把地圖座標轉換為模型檢視投影矩陣。您可以使用此函式將地圖座標轉譯為世界空間、攝影機空間和螢幕空間。
- 如有任何因素造成算繪環境遺失,系統會呼叫
onContextLost()
,其中任何既有的 GL 狀態都不再需要使用,請加以清除。 onStateUpdate({gl})
會更新算繪迴圈外的 GL 狀態,並在呼叫requestStateUpdate
時加以叫用。這會採用WebGLStateOptions
執行個體,其中包含單一欄位:gl
是基本地圖使用的WebGLRenderingContext
控制代碼。
- 使用
WebGLOverlayView.setMap(null)
從地圖中移除疊加層時,系統會呼叫onRemove()
,請務必移除其中的所有中繼物件。
舉例來說,以下是所有生命週期掛鉤的基本實作方式:
const webglOverlayView = new google.maps.WebGLOverlayView();
webglOverlayView.onAdd = () => {
// Do setup that does not require access to rendering context.
}
webglOverlayView.onContextRestored = ({gl}) => {
// Do setup that requires access to rendering context before onDraw call.
}
webglOverlayView.onStateUpdate = ({gl}) => {
// Do GL state setup or updates outside of the render loop.
}
webglOverlayView.onDraw = ({gl, transformer}) => {
// Render objects.
}
webglOverlayView.onContextLost = () => {
// Clean up pre-existing GL state.
}
webglOverlayView.onRemove = () => {
// Remove all intermediate objects.
}
webglOverlayView.setMap(map);
重設 GL 狀態
WebGL 疊加層檢視可顯示基本地圖的 WebGL 算繪環境。因此,完成算繪物件時,請務必將 GL 狀態重設為原始狀態。如未能重設 GL 狀態,可能會導致 GL 狀態衝突,造成地圖和您指定的任何物件算繪失敗。
GL 狀態重設通常會在 onDraw()
掛鉤中處理。例如,Three.js 提供的輔助函式會清除 GL 狀態的任何變更:
webglOverlayView.onDraw = ({gl, transformer}) => {
// Specify an object to render.
renderer.render(scene, camera);
renderer.resetState();
}
如果地圖或物件無法算繪,很可能表示 GL 狀態尚未重設。
座標轉換
提供經緯度座標的組合以及海拔高度,即可指定物件在向量地圖上的位置。不過,3D 圖形是在世界空間、攝影機空間或螢幕空間中指定。為方便將地圖座標轉換為更常用的空間,WebGL 疊加層檢視會在 onDraw()
掛鉤中提供 coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr,
scalarArr)
輔助函式,該掛鉤會使用下列項目並傳回 Float64Array
:
latLngAltitude
:緯度/經度/海拔高度座標,格式為LatLngAltitude
或LatLngAltitudeLiteral
。rotationArr
:Float32Array
的歐拉旋轉角度 (以度為單位)。scalarArr
:要套用至基軸的純量Float32Array
。
例如,以下程式碼使用 fromLatLngAltitude()
在 Three.js 中建立攝影機投影矩陣:
const camera = new THREE.PerspectiveCamera();
const matrix = coordinateTransformer.fromLatLngAltitude({
lat: mapOptions.center.lat,
lng: mapOptions.center.lng,
altitude: 120,
});
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
範例
以下簡單示範如何使用 Three.js (常用開放原始碼 WebGL 程式庫) 在地圖上放置 3D 物件。若想瞭解如何使用 WebGL 疊加層檢視建立本頁上方的範例,請到程式碼研究室:打造採用 WebGL 加速技術的地圖體驗,查看完整逐步操作說明。
const webglOverlayView = new google.maps.WebGLOverlayView();
let scene, renderer, camera, loader;
webglOverlayView.onAdd = () => {
// Set up the Three.js scene.
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // Soft white light.
scene.add(ambientLight);
// Load the 3D model with GLTF Loader from Three.js.
loader = new GLTFLoader();
loader.load("pin.gltf");
}
webglOverlayView.onContextRestored = ({gl}) => {
// Create the Three.js renderer, using the
// maps's WebGL rendering context.
renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
}
webglOverlayView.onDraw = ({gl, transformer}) => {
// Update camera matrix to ensure the model is georeferenced correctly on the map.
const matrix = transformer.fromLatLngAltitude({
lat: mapOptions.center.lat,
lng: mapOptions.center.lng,
altitude: 120,
});
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
// Request a redraw and render the scene.
webglOverlayView.requestRedraw();
renderer.render(scene, camera);
// Always reset the GL state.
renderer.resetState();
}
// Add the overlay to the map.
webglOverlayView.setMap(map);