空间 Web 新特性
What's new for the spatial web
2025年6月9日
一句话判断
HTML 有了一个新元素 <model>——它不是又一个 3D viewer 库,而是浏览器原生的立体渲染管道,3D 模型直接穿出页面表面以真实深度呈现,配合拖拽和 Quick Look 用户可以把模型从网页里”拿”出来放到自己空间里。
这场 Session 讲了什么
visionOS 上的 Safari 迎来了三个重磅空间 Web 特性。第一个是全新的 HTML <model> 元素,用于在网页中嵌入 USDZ 格式的 3D 模型。模型以立体方式渲染在页面表面之后,用户可以旋转、拖拽到 Quick Look 中以真实尺寸查看。支持通过 IBL(image-based lighting)自定义光照、通过 entityTransform 控制位置和旋转、通过 currentTime 控制 USDZ 文件内的动画时间轴,甚至可以用 Three.js 在浏览器中动态生成 USDZ 文件。
第二个是沉浸式媒体支持扩展:除了去年已有的全景和空间照片,新增了 180 度、360 度、广角视频以及 Apple Immersive Video。这些内容在页面中以 2D 方式内联显示,全屏后自动以正确的投影方式包裹用户。
第三个是 developer preview 的 Website Environments 功能——通过 <link rel="spatial-backdrop"> 为网站指定一个 USDZ 环境,用户可以选择沉浸在这个环境中浏览你的网站。
值得深挖的点
<model> 元素的渲染模型
<model> 元素不是在页面平面内渲染 3D 内容,而是把元素区域当作一个”窗口”,模型渲染在页面表面之后的虚拟空间中。这个设计避免了模型”穿出”页面表面的视觉问题——因为模型永远在页面后面。当你设置 stagemode="orbit" 时,浏览器会自动缩放和偏移模型,确保旋转过程中模型始终在页面表面之后。
这个渲染模型带来了有趣的 CSS 组合可能性。Session 中展示了一个相机产品页:模型元素延伸到右侧面板下面,面板用 backdrop-filter: blur() 实现磨砂玻璃效果,linear-gradient 在边缘制造高光,营造出强烈的层次感。这些都是老的 CSS 技巧,但和模型元素的深度效果结合后效果出众。
一个需要注意的坑:模型的背景色必须在 <model> 元素本身上设置(background-color),不能设置在祖先元素上。因为整个 <model> 区域被虚拟空间替换,祖先的背景色不会穿透。如果有 alpha 通道,也会被转为不透明色。
entityTransform 与 currentTime 的组合玩法
entityTransform 是一个 DOMMatrix,控制模型在虚拟空间中的位置、旋转和缩放。默认值由浏览器计算,保证模型居中适配。注意只支持 uniform scaling、rotation 和 translation,不支持非均匀缩放或错切——赋值一个含不支持操作的矩阵会报错。单位约定是 1 USDZ 厘米 = 1 CSS 厘米(约 38px),但 visionOS 上 Safari 窗口的物理尺寸随距离变化,所以内联显示时没有真实的物理尺寸关系。如果需要真实尺寸展示,让用户拖拽到 Quick Look。
currentTime 控制 USDZ 文件内动画的时间轴位置,单位是秒。关键特性是没有隐式动画——设置 currentTime 后模型立即跳转到对应状态。这让你可以把动画时间轴和 UI 控件(如 slider、scroll 事件)绑定。Session 中的相机示例:currentTime 驱动屏幕开合动画,entityTransform 驱动整机移动动画,两者组合创造了复杂的产品展示交互。
代码片段
嵌入 USDZ 模型并提供 2D 降级方案:
<model src="camera.usdz">
<img src="camera-render.jpg" alt="相机产品图">
</model>
通过 JavaScript 控制模型旋转到特定角度:
const model = document.querySelector('model');
model.ready.then(() => {
const matrix = model.entityTransform;
matrix.rotateAxisAngle(0, 1, 0, 90); // 绕 Y 轴旋转 90 度
model.entityTransform = matrix;
});
用 slider 控制 USDZ 动画时间轴:
<model id="camera" src="camera.usdz" autoplay></model>
<input type="range" min="2" max="3" step="0.01" id="slider">
<script>
slider.addEventListener('input', (e) => {
document.getElementById('camera').currentTime = parseFloat(e.target.value);
});
</script>
最佳实践
建议始终为 <model> 元素提供 fallback 内容。可以是静态图片,也可以是 model-viewer 等库的 2D 渲染。检测支持时用 window.HTMLModelElement 而不是 user agent 字符串——后者不可靠且脆弱。
优先对 USDZ 文件做体积优化。超过 10MB 的模型加载需要好几秒,用 Mac 的 Preview 导出压缩纹理版本。同时利用 model.ready Promise 显示加载指示器,避免用户在等待中离开。
避免在 IBL 文件中使用 JPEG 格式。推荐 OpenEXR 或 Radiance HDR 格式,它们能表示多个数量级的亮度范围,让反射效果更真实。
还有什么值得关注
- Three.js 的 USDZ 导出器可以在浏览器中动态生成 USDZ 文件,支持用户自定义内容(如刻字、换色)后仍可拖拽到 Quick Look 中查看。
- 沉浸式媒体只需用现有的
<video>元素嵌入,不需要新元素。全屏播放时自动应用正确投影。支持 HLS 流媒体。 - Website Environments 功能需要在 Settings > Safari > Advanced > Feature Flags 中手动开启,是 developer preview 状态。