用 WebXR 构建沉浸式网页体验
Build immersive web experiences with WebXR
2024年6月10日
一句话判断
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 管线,帧率表现不错。