SwiftUI 进入第三维:Volume、Model3D 与 3D 手势
Take SwiftUI to the next dimension
2023年6月5日
一句话判断
从 Model3D 加载 USDZ 到 RealityView 的 attachments API,这场 Session 是 SwiftUI 3D 内容开发的实操手册。
这场 Session 讲了什么
Mark 从 SwiftUI 团队出发,以 World 示例 App 为载体,讲解了在 Volume 容器中使用 SwiftUI 展示 3D 内容的完整流程:
Volume 容器。使用 .windowStyle(.volumetric) 创建固定尺寸的 3D 容器。Volume 保持真实尺寸不变——不管距离多远,1 米宽的 Volume 永远是 1 米宽。支持从任何角度查看。
Model3D 视图。加载 USDZ 文件的 SwiftUI 视图,类似 AsyncImage 的设计。提供 loading/success/failure 三个阶段,用 .resizable() 和 .scaledToFit() 控制尺寸。默认背面对齐,可以用 .frame(depth:) 和 depthAlignment 改为正面对齐。
3D 布局和动画。用 TimelineView 驱动基于时间的动画,配合 Rotation3DEffect 实现 3D 旋转。containerRelativeFrame 让视图尺寸相对于容器而非设备屏幕,配合 horizontalSizeClass 做自适应布局。
RealityView 和 Attachments。RealityView 是 SwiftUI 中使用 RealityKit 的入口。Attachments API 让你把 SwiftUI 视图(文字标签、编辑控件)绑定到 RealityKit Entity 上。这些视图是活的——可以响应状态变化、运行动画、处理手势。
3D 手势。在 Volume 中支持拖拽、旋转、缩放等空间手势。
值得深挖的点
Model3D 的深度对齐。3D 内容默认背面与容器对齐,这在从侧面看时会显得不自然。设置 depthAlignment: .front 让内容正面对齐,从任何角度观察都更协调。
Attachments 的”活视图”特性。和 Canvas API 的静态快照不同,Attachments 中的 SwiftUI 视图是真实存在的视图——它们会响应 @State 变化、运行动画、处理用户交互。这让 3D 场景中的 2D 标签变得非常灵活。
containerRelativeFrame 的跨平台价值。这个 API 不只适用于空间计算——在 iOS/iPadOS 上也能用。让视图尺寸基于最近的容器(ScrollView 列、NavigationSplitView 列、窗口)而非整个屏幕,布局更精确。
代码片段
// Model3D 加载 3D 模型
Model3D(named: "Moon") { phase in
switch phase {
case .success(let model):
model.resizable().scaledToFit()
case .failure(let error):
Text(error.localizedDescription)
default:
ProgressView() // 加载中
}
}
.frame(depth: 100, depthAlignment: .front) // 正面对齐
// 3D 旋转动画
TimelineView(.animation) { context in
CelestialObjectView(name: "Earth")
.rotation3DEffect(
.degrees(context.date.timeIntervalSinceReferenceDate * 10),
axis: (x: 0, y: 1, z: 0)
)
}
// RealityView + Attachments:在 3D 场景中放置 SwiftUI 标签
RealityView { content in
let earth = try await Entity(named: "Earth")
content.add(earth)
} attachments: {
// 为每个地点创建标签
ForEach(favoritePlaces) { place in
Text(place.name)
.glassBackgroundEffect()
.tag(place.id) // 用 tag 标识
}
}
// attachments 会自动匹配到 RealityKit Entity
最佳实践
- 简单的 3D 展示用 Model3D,需要自定义交互和渲染用 RealityView。
- 注意 3D 内容的深度对齐,默认的背面模式可能不是你想要的。
- 用 containerRelativeFrame 做基于容器的自适应布局,配合 horizontalSizeClass 区分设备。
- Attachments 中的视图可以放任何 SwiftUI 组件,包括按钮和手势。
- 给 3D 内容添加玻璃背景效果的标签,确保在任何背景下都可读。
还有什么值得关注
- “Build spatial experiences with RealityKit” 是 RealityView 的姊妹 Session
- “Enhance your spatial computing app with RealityKit” 讲了更多 RealityKit 高级功能
- “Elevate your windowed app for spatial computing” 讲了窗口 App 的优化
- World 示例 App 是学习 3D SwiftUI 的最佳参考项目