XRSession:requestAnimationFrame() 方法

实验性: 这是一个 实验性技术
在生产环境中使用此功能之前,请仔细查看 浏览器兼容性表格

安全上下文:此功能仅在 安全上下文(HTTPS)中可用,并且仅在某些或所有 支持的浏览器 中可用。

XRSession 方法 requestAnimationFrame() 与同名的 Window 方法类似,它计划在浏览器下次准备好将会话的虚拟环境绘制到 XR 显示器时执行回调。指定的回调将在下次重绘之前执行一次;如果您希望它在下一次重绘时执行,则必须再次调用 requestAnimationFrame()。这可以在回调本身中完成。

回调以两个参数作为输入:一个 XRFrame,描述会话中所有跟踪对象的当前状态,以及一个时间戳,您可以使用它来计算任何所需的动画更新。

您可以通过调用 cancelAnimationFrame() 取消先前计划的动画。

注意:尽管这些方法与 Window 接口提供的全局 requestAnimationFrame() 函数之间存在明显的相似之处,但您绝不能将它们视为可互换的。无法保证后者在沉浸式 XR 会话正在进行时能否正常工作。

语法

js
requestAnimationFrame(animationFrameCallback)

参数

animationFrameCallback

一个在下次重绘之前被调用的函数,以便您可以根据经过的时间、动画、用户输入的变化等更新和渲染 XR 场景。回调接收两个参数作为输入。

时间

一个 DOMHighResTimeStamp,指示从 WebXR 设备接收更新的查看器状态的时间偏移量。

xrFrame

一个 XRFrame 对象,描述会话跟踪的对象的状态。这可以用于获取查看器和场景本身的姿势,以及渲染 AR 或 VR 场景帧所需的其它信息。

返回值

一个整数值,用作唯一的非零 ID 或句柄,如果您需要移除挂起的动画帧请求,则可以将其传递给 cancelAnimationFrame()

示例

以下示例使用“内联”模式请求 XRSession,以便它可以显示在 HTML 元素中(无需单独的 AR 或 VR 设备)。

注意: 实际应用应该检查设备和用户代理是否都支持 WebXR API,然后检查它们是否都支持通过 XRSystem.isSessionSupported() 所需的会话类型。

js
// 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 动画之间无缝转换。

js
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 设备 API
# dom-xrsession-requestanimationframe

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅