XRSession: requestAnimationFrame() 方法

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

實驗性: 這是一項實驗性技術
在生產中使用此技術之前,請仔細檢查瀏覽器相容性表格

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

與同名的 Window 方法類似,XRSession 方法 requestAnimationFrame() 會安排一個回撥函式,在下次瀏覽器準備好將會話的虛擬環境繪製到 XR 顯示器時執行。指定的 [回撥函式](#animationframecallback) 會在下一次重繪之前執行一次;如果您希望它在後續的重繪時執行,您必須再次呼叫 requestAnimationFrame()。這可以在回撥函式內部完成。

回撥函式接受兩個引數:一個 XRFrame,描述了會話中所有跟蹤物件的 [狀態](#xrframe);以及一個您可以用於計算任何所需動畫更新的時間戳。

您可以透過呼叫 cancelAnimationFrame() 來取消先前排程的動畫。

注意: 儘管這些方法與 Window 介面提供的全域性 requestAnimationFrame() 函式有明顯的相似之處,但您不得將它們視為可互換的。在沉浸式 XR 會話進行期間,不保證後者能夠正常工作。

語法

js
requestAnimationFrame(animationFrameCallback)

引數

animationFrameCallback

在下一次重繪之前呼叫的函式,以便您根據經過的時間、動畫、使用者輸入更改等來更新和渲染 XR 場景。回撥函式接收兩個引數作為輸入。

時間

一個 DOMHighResTimeStamp,表示從 WebXR 裝置接收到更新後的檢視器狀態的時間偏移量。

xrFrame

一個 XRFrame 物件,描述了會話正在跟蹤的物件的 [狀態](#xrframe)。這可用於獲取檢視器和場景本身的姿態,以及渲染 AR 或 VR 場景幀所需的其他資訊。

返回值

一個整數值,作為唯一的非零 ID 或控制代碼,如果您需要刪除掛起的動畫幀請求,可以將其傳遞給 cancelAnimationFrame()

示例

以下示例請求使用“inline”模式的 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 Device API
# dom-xrsession-requestanimationframe

瀏覽器相容性

另見