Highlight
Apple 将原生的
<model>元素从 visionOS 扩展到 iOS、iPadOS 和 macOS,开发者写一行 HTML 就能在网页中嵌入交互式 3D 模型,无需引入任何 JavaScript 库,且支持 AR Quick Look 和立体渲染。
核心内容
在网页上展示 3D 模型,过去只有两条路:引入 Google 的 model-viewer,或者用 Three.js 自己搭一套渲染管线。两条路都要加载大量 JavaScript,在 visionOS 上还要额外处理立体渲染(stereoscopic rendering)的性能损耗。
Apple 在 visionOS 上率先推出了原生的 <model> 元素。现在,这个元素来到了 iOS、iPadOS 和 macOS 的 Safari 中。同一行标记,在所有 Apple 平台上都能工作。
(00:37)
<model> 是原生 HTML 元素,由浏览器直接渲染。visionOS 上自带立体渲染,iPhone 和 iPad 上也能流畅交互。它还是一个正在 W3C 推进的 Web 标准,代码具有向前兼容性。对于不支持该元素的浏览器,官方提供了 polyfill 作为降级方案。
(00:48)
Session 以一个户外电商网站为例,演示了从获取 3D 资产到上线优化的完整流程。获取资产有三种途径:用 iPhone 扫描实物、在 Blender 等工具中从零创建、或者用 AI 生成。Session 中演示了用几张露营槌的照片,通过 Tripo3D 在几分钟内生成 USDZ 模型的过程。
(02:22)
USDZ 是 Apple 推荐的格式。它是 Universal Scene Description 的 zip 打包格式,把几何体、材质、纹理、动画都封装在一个文件里。Safari 也支持其他格式,但从兼容性角度,USDZ 是首选。
(03:17)
详细内容
加载模型与降级处理
<model> 的用法和 <img> 或 <video> 一样直观。用 src 属性指向 USDZ 文件即可:
<!-- 使用 src 属性 -->
<model src="mallet.usdz"></model>
<!-- 使用 <source> 子元素指定 MIME 类型 -->
<model>
<source src="mallet.usdz" type="model/vnd.usdz+zip">
</model>
(04:19)
降级也很直接。在 <model> 内部放一张 <img>,不支持该元素的浏览器会显示图片:
<model id="mallet" src="mallet.usdz">
<img src="mallet.png"
alt="Rubber mallet with wooden handle">
</model>
(04:39)
关键点:
<model>内部嵌套<img>实现优雅降级- 旧版 Safari 和其他不支持
<model>的浏览器会自动渲染图片 - 用户至少能看到产品的静态视图
3D 模型文件通常有几十 MB,加载需要时间。ready 属性返回一个 Promise,在模型加载完成时 resolve:
<model id="mallet" src="mallet.usdz"></model>
<script>
const model = document.getElementById("mallet");
model.ready.then(result => {
// Hide the loading indicator
}).catch(error => {
// Loading failed, show fallback
});
</script>
(05:09)
关键点:
model.ready是一个 Promise,模型解析完毕时 resolve- 在
then回调中隐藏 loading 动画 - 在
catch回调中处理加载失败,显示降级内容
对于完全不支持 <model> 的浏览器,可以用 polyfill:
<script type="module">
if (!window.HTMLModelElement) {
import("model-element-polyfill.js").then(() => {
// Polyfill ready to use
});
}
</script>
(05:39)
关键点:
- 通过
window.HTMLModelElement检测原生支持 - 不支持时动态加载 polyfill 脚本
- polyfill 无法模拟 visionOS 上的立体渲染等硬件相关特性
样式与交互
<model> 渲染在自己的虚拟空间中,不会继承页面的背景。需要直接给元素设置 background-color:
<model id="mallet" src="mallet.usdz"></model>
<style>
model {
background-color: #f4f1ec;
}
</style>
(06:13)
关键点:
- 背景色始终不透明,带透明度的颜色会被转换为不透明色
- 直接对
<model>元素写 CSS 即可控制外观
最简单的交互是让用户自由旋转模型。加一个 stagemode="orbit" 属性:
<model id="mallet"
src="mallet.usdz"
stagemode="orbit">
</model>
(06:47)
关键点:
stagemode="orbit"让用户可以左右自由旋转模型- 上下倾斜后松手,模型会弹簧回弹到原始角度
- 模型会自动缩小一点,防止旋转时部分被裁剪
如果需要自定义视角,用 JavaScript 操控 entityTransform。注意要先禁用 stagemode:
<model id="boot" src="boot.usdz"></model>
<button id="button-side">Side</button>
<button id="button-reset">Reset</button>
<script>
const model = document.getElementById("boot");
const initialTransform = model.entityTransform;
document.getElementById("button-side")
.addEventListener("click", () => {
const transform = new DOMMatrix();
transform.rotateSelf(0, 135, 0);
model.entityTransform = transform;
});
document.getElementById("button-reset")
.addEventListener("click", () => {
model.entityTransform = initialTransform;
});
</script>
(07:31)
关键点:
- 使用
entityTransform前需移除stagemode属性或设为"none" DOMMatrix表示模型在 3D 空间中的方位rotateSelf(0, 135, 0)绕 Y 轴旋转 135 度- 提前保存
initialTransform用于复位 - 自定义旋转可能导致模型被裁剪,需要手动调整位置
直接切换视角会显得很生硬。用 requestAnimationFrame 实现平滑过渡:
const model = document.getElementById("boot");
const duration = 500;
let currentAngle = 0;
let animationId = null;
function animateTo(targetAngle) {
if (animationId) cancelAnimationFrame(animationId);
const startAngle = currentAngle;
const startTime = performance.now();
function step(now) {
const progress = Math.min((now - startTime) / duration, 1);
const ease = 1 - Math.pow(1 - progress, 3);
currentAngle = startAngle + (targetAngle - startAngle) * ease;
model.entityTransform = new DOMMatrix().rotateSelf(0, currentAngle, 0);
if (progress < 1) animationId = requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
document.getElementById("button-side").addEventListener("click", () => animateTo(135));
document.getElementById("button-reset").addEventListener("click", () => animateTo(0));
(08:35)
关键点:
- 先
cancelAnimationFrame取消正在运行的动画,防止冲突 ease = 1 - Math.pow(1 - progress, 3)实现 ease-out 缓动- 每帧用新的
DOMMatrix更新entityTransform - 500 毫秒的时长兼顾了响应速度和视觉流畅度
动画播放
USDZ 文件可以内嵌在 Blender 或 Maya 中制作的动画。<model> 默认播放第一条动画轨道,用 JavaScript 控制播放速率:
<model id="bottle" src="bottle.usdz"></model>
<button id="button-play" onclick="play(5)">
Play
</button>
<button id="button-reverse" onclick="play(-5)">
Reverse
</button>
<script>
const model = document.getElementById("bottle");
function play(rate) {
model.playbackRate = rate;
model.play();
}
</script>
(10:07)
关键点:
model.play()启动动画播放playbackRate控制播放速度,正值正向播放,负值倒放- 示例中用 5 和 -5 实现 5 倍速正向和反向播放
AR Quick Look
把 <model> 包在 <a rel="ar"> 标签中,iOS 和 iPadOS 用户点击后直接进入 AR Quick Look:
<a rel="ar" href="bottle.usdz">
<model id="boot" src="bottle.usdz"></model>
</a>
(11:06)
关键点:
<a rel="ar">指向与<model>相同的 USDZ 文件- iOS/iPadOS 上唤起原生 AR 体验
- visionOS 上模型以立体渲染呈现,用户可以把产品从页面中”拉出来”查看
命令行优化工具
usdcrush 可以大幅压缩 USDZ 文件体积。Session 中的示例把 7.9 MB 的靴子模型压到了 1.9 MB,画质没有肉眼可见的损失。
(12:39)
usdrecord 可以从 USDZ 文件批量渲染缩略图或降级图片。可以写脚本遍历整个商品目录自动生成 fallback 图片,不需要手动截图。
(13:10)
这两个工具 macOS 已预装,属于 USD 工具套件的一部分。
核心启发
1. 电商产品页一键 3D 化
把现有商品图片替换成 <model> 标签,加载同一个 USDZ 文件。用户可以在页面上旋转查看产品细节,点击后进入 AR 模式把商品放在家里看效果。入口就是一行 HTML。
- 实现思路:用
usdrecord批量生成 fallback 图片,<model>内部嵌套<img>做降级,外层包<a rel="ar">实现 AR 入口
2. 作品集网站的交互式 3D 展示
设计师、建筑师可以在个人网站上直接展示 3D 作品。访客不用下载任何文件,在浏览器里就能旋转、缩放模型。用 stagemode="orbit" 一行代码搞定交互。
- 实现思路:导出 USDZ 格式,
<model stagemode="orbit">直接嵌入,配合 CSS 设置背景色融入页面风格
3. 教育类应用的 3D 模型讲解
生物课展示细胞结构、历史课展示文物复原模型。用 entityTransform 和 requestAnimationFrame 实现预设视角切换,点击”剖面图”按钮平滑旋转到特定角度。
- 实现思路:预定义几个视角角度,用
animateTo()函数实现带缓动的视角切换,配合playbackRate控制模型内置动画
4. AI 生成 3D 资产的工作流
用 Tripo3D 或 Meshy.ai 从几张产品照片生成 USDZ 模型,用 usdcrush 压缩后部署。整个流程不需要专业 3D 建模技能。
- 实现思路:照片 -> AI 生成 USDZ ->
usdcrush压缩 ->usdrecord生成 fallback 图片 -> 上线
5. 跨平台 3D 内容分发
同一套 HTML 代码在 iPhone、iPad、Mac 和 Vision Pro 上都能展示 3D 内容。visionOS 上还有立体深度效果。配合 polyfill 还能覆盖不支持原生 <model> 的浏览器。
- 实现思路:检测
window.HTMLModelElement,不存在时加载 polyfill,保证最大兼容性
关联 Session
- Explore immersive website environments — 深入了解 visionOS 上的沉浸式网站环境 API
- What’s new for the spatial web — WWDC25 空间 Web 特性深度讲解
- What’s new in USD and MaterialX — USD 生态系统和命令行工具详解
- Get started with Reality Composer Pro 3 — 3D 资产创作工具
- Create 3D models for your spatial apps — 3D 模型制作最佳实践
评论
GitHub Issues · utterances