WebGL 叠加视图

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

查看示例

借助 WebGL 叠加视图,您可以直接使用 WebGL 或 Three.js 等热门图形库向地图添加内容。WebGL 叠加视图可以直接访问 Google Maps Platform 用于渲染矢量基本地图的相同 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 叠加视图提供了一组在矢量基本地图的 WebGL 渲染上下文生命周期的不同时间调用的钩子。您可以在这些生命周期钩子中设置、绘制和拆除您希望在叠加层中渲染的任何内容。

  • 创建叠加层时调用 onAdd()。使用该 API 可以在绘制叠加层(不需要立即访问 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
  • 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 加速的地图体验”Codelab

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);