Build immersive web experiences with WebXR
Safari & Web 进阶 20m

用 WebXR 构建沉浸式网页体验

Build immersive web experiences with WebXR

2024年6月10日

在 Apple 官方观看视频

一句话判断

Apple Vision Pro 上的 Safari 终于支持 WebXR,这意味着你的网站现在可以直接启动全沉浸式 VR 体验,无需安装任何 App。

这场 Session 讲了什么

这场 Session 正式宣布 Safari on visionOS 2.0 支持 WebXR 标准。WebXR 是 W3C 制定的网页沉浸式体验标准,Safari 的实现覆盖了完整的 VR 会话能力——从用户授权、WebGL 渲染到手势输入和会话管理。Apple 还特别强调了隐私和安全设计:WebXR 会话必须由用户主动触发,所有内容强制 HTTPS,视线追踪数据只在用户捏合时才暴露位置信息。

演示部分用了一个国际象棋 VR 场景,展示了从网页一键进入完全沉浸式的 3D 环境的完整流程。整体体验已经非常成熟,不需要原生 App 就能实现高质量的 VR 交互。

值得深挖的点

WebXR 的隐私模型:克制比功能更重要

Apple 在 WebXR 的实现上展现了典型的”安全先行”策略。整个安全模型分三层:第一层是网络层,强制 HTTPS 防止中间人注入;第二层是 iframe 隔离,嵌入 WebXR 的 iframe 必须声明 allow="xr-spatial-tracking",这意味着广告代码不可能偷偷启动 VR;第三层是用户意图验证,WebXR 会话不能自动启动,必须有明确的用户交互(比如点击按钮)。

在输入隐私上 Apple 更是谨慎。Vision Pro 的 gaze + pinch 交互模型中,用户注视的位置是高度敏感信息。Safari 的做法是:WebXR 只在用户捏合的那一刻才暴露注视点坐标,手部位置也只在捏合期间可见。这种”最小必要披露”原则和 Meta Quest 的实现形成了鲜明对比——后者给了 WebXR 更多的连续追踪权限。Apple 的做法更保守,但对于 Web 这个”不可信环境”来说是正确的选择。

从 WebGL 到 WebXR 的技术路径

Session 清晰地描绘了技术栈:底层是 WebGL 做硬件加速渲染,WebXR 负责管理沉浸式会话(隐藏浏览器 UI、接管渲染管线)。但直接写 WebGL 代码量惊人——渲染一个正方形就需要写 shader、定义顶点、处理矩阵运算。Session 推荐了多个 WebGL 框架:Three.js、Babylon.js、PlayCanvas 适合用 JavaScript 构建的场景;Wonderland Engine 提供可视化编辑器;A-Frame 用声明式 HTML 构建 3D 场景。

A-Frame 的方案对 Web 开发者最友好。几个自定义 HTML 标签就能搭建一个带天空盒、几何体和动画的 3D 场景,底层实际上是在 Three.js 之上封装。这种渐进式增强的设计让新手可以用 HTML 快速上手,高级用户随时可以切换到 JavaScript 做深度定制。

代码片段

用 A-Frame 快速搭建 VR 场景

<!-- 引入 A-Frame 库后,用声明式 HTML 构建完整 3D 场景 -->
<script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>

<a-scene>
  <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>
</a-scene>

场景:想在网页里快速放几个 3D 物体并支持 VR 查看。坑:A-Frame 默认的交互模型需要额外配置才能适配 Vision Pro 的 gaze + pinch 输入。

请求 WebXR 会话

// 检查设备是否支持沉浸式 VR
if (navigator.xr) {
  const isSupported = await navigator.xr.isSessionSupported('immersive-vr');
  if (isSupported) {
    // 必须在用户交互(如按钮点击)中调用,不能自动启动
    const session = await navigator.xr.requestSession('immersive-vr', {
      requiredFeatures: ['local-floor']
    });
    // 将 WebGL 上下文与 XR 会话绑定
    const gl = canvas.getContext('webgl2', { xrCompatible: true });
    gl.makeXRCompatible();
  }
}

场景:从网页进入 VR 模式的标准入口代码。坑:requestSession 必须在用户手势的回调中调用,异步等待后再调用会被浏览器拒绝。

iframe 中嵌入 WebXR 内容

<!-- 父页面必须声明 allow 属性,否则 iframe 中的 XR 内容无法运行 -->
<iframe
  src="https://example.com/vr-experience"
  allow="xr-spatial-tracking"
></iframe>

场景:第三方 XR 内容需要嵌入到主页面。坑:忘记加 allow="xr-spatial-tracking" 会导致 iframe 内的 WebXR 请求静默失败,没有任何报错提示。

最佳实践

新项目: 如果你在做 Vision Pro 相关的 3D 展示或交互体验,WebXR 是值得优先考虑的方案。不需要走 App Store 审核,不需要用户下载,打开网页就能用。推荐从 A-Frame 开始原型验证,复杂场景再迁移到 Three.js 或 Babylon.js。HTTPS 是硬性要求,开发阶段可以用 localhost 豁免。

已有项目: 如果你的网站已经有 3D 内容(产品展示、虚拟展厅等),添加 WebXR 支持的工作量比想象中小。核心是检测 navigator.xr 的可用性,在支持的设备上显示”进入 VR”按钮,然后用 requestSession 切换到沉浸式模式。关键是不要在非 XR 设备上暴露 VR 相关的 UI。

还有什么值得关注

  • WebXR 标准被设计为”面向未来兼容”(future-resistant),新硬件形态出现时 API 不需要大改。
  • 用户可以随时通过数码表冠或系统手势退出 VR 会话,这是标准强制要求的保底退出机制。
  • visionOS 上 WebXR 的渲染性能已经接近原生,Apple 用了硬件加速的 WebGL 管线,帧率表现不错。
WWDC 2024