XRSession: requestAnimationFrame() 方法
与同名的 Window 方法类似,XRSession 方法 requestAnimationFrame() 会安排一个回调函数,在下次浏览器准备好将会话的虚拟环境绘制到 XR 显示器时执行。指定的 [回调函数](#animationframecallback) 会在下一次重绘之前执行一次;如果您希望它在后续的重绘时执行,您必须再次调用 requestAnimationFrame()。这可以在回调函数内部完成。
回调函数接受两个参数:一个 XRFrame,描述了会话中所有跟踪对象的 [状态](#xrframe);以及一个您可以用于计算任何所需动画更新的时间戳。
您可以通过调用 cancelAnimationFrame() 来取消先前调度的动画。
注意: 尽管这些方法与 Window 接口提供的全局 requestAnimationFrame() 函数有明显的相似之处,但您不得将它们视为可互换的。在沉浸式 XR 会话进行期间,不保证后者能够正常工作。
语法
requestAnimationFrame(animationFrameCallback)
参数
- animationFrameCallback
- 
在下一次重绘之前调用的函数,以便您根据经过的时间、动画、用户输入更改等来更新和渲染 XR 场景。回调函数接收两个参数作为输入。 - 时间
- 
一个 DOMHighResTimeStamp,表示从 WebXR 设备接收到更新后的查看器状态的时间偏移量。
- xrFrame
- 
一个 XRFrame对象,描述了会话正在跟踪的对象的 [状态](#xrframe)。这可用于获取查看器和场景本身的姿态,以及渲染 AR 或 VR 场景帧所需的其他信息。
 
返回值
一个整数值,作为唯一的非零 ID 或句柄,如果您需要删除挂起的动画帧请求,可以将其传递给 cancelAnimationFrame()。
示例
以下示例请求使用“inline”模式的 XRSession,以便它可以在 HTML 元素中显示(无需单独的 AR 或 VR 设备)。
注意: 实际应用程序应首先检查设备和用户代理是否支持 WebXR API,然后再通过 XRSystem.isSessionSupported() 检查它们是否都支持所需的会话类型。
// Obtain XR object
const XR = navigator.xr;
// Request a new XRSession
XR.requestSession("inline").then((xrSession) => {
  xrSession.requestAnimationFrame((time, xrFrame) => {
    const viewer = xrFrame.getViewerPose(xrReferenceSpace);
    gl.bindFramebuffer(xrWebGLLayer.framebuffer);
    for (const xrView of viewer.views) {
      const xrViewport = xrWebGLLayer.getViewport(xrView);
      gl.viewport(
        xrViewport.x,
        xrViewport.y,
        xrViewport.width,
        xrViewport.height,
      );
      // WebGL draw calls will now be rendered into the appropriate viewport.
    }
  });
});
以下示例直接摘录自规范草案。该示例演示了一种设计模式,可确保通过 Window.requestAnimationFrame 创建的非沉浸式动画与沉浸式 XR 动画之间实现无缝过渡。
let xrSession = null;
function onWindowAnimationFrame(time) {
  window.requestAnimationFrame(onWindowAnimationFrame);
  // This may be called while an immersive session is running on some devices,
  // such as a desktop with a tethered headset. To prevent two loops from
  // rendering in parallel, skip drawing in this one until the session ends.
  if (!xrSession) {
    renderFrame(time, null);
  }
}
// The window animation loop can be started immediately upon the page loading.
window.requestAnimationFrame(onWindowAnimationFrame);
function onXRAnimationFrame(time, xrFrame) {
  xrSession.requestAnimationFrame(onXRAnimationFrame);
  renderFrame(time, xrFrame);
}
function renderFrame(time, xrFrame) {
  // Shared rendering logic.
}
// Assumed to be called by a user gesture event elsewhere in code.
function startXRSession() {
  navigator.xr.requestSession("immersive-vr").then((session) => {
    xrSession = session;
    xrSession.addEventListener("end", onXRSessionEnded);
    // Do necessary session setup here.
    // Begin the session's animation loop.
    xrSession.requestAnimationFrame(onXRAnimationFrame);
  });
}
function onXRSessionEnded() {
  xrSession = null;
}
规范
| 规范 | 
|---|
| WebXR Device API # dom-xrsession-requestanimationframe | 
浏览器兼容性
加载中…