WebGL 疊加層檢視

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

查看範例

透過 WebGL 疊加層檢視,您可以直接使用 WebGL 或常用圖像格式 (例如 Three.js) 在地圖上新增內容。WebGL 疊加層檢視可讓您直接存取 Google 地圖平台用來轉譯向量基本地圖的 WebGL 轉譯結構定義。使用共用轉譯結構定義的好處,包括具備 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 疊加層檢視提供一系列在掛鉤向量算繪生命週期的生命週期中呼叫的掛鉤。這些生命週期掛鉤可設定、繪製及拆解要依照重疊方式呈現的任何內容。

  • 系統會在建立疊加層時呼叫 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:緯度/經度/高度座標為 LatLngAltitudeLatLngAltitudeLiteral
  • rotationArrFloat32Array 的旋轉角度 (以度為單位)。
  • 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);