布景
在体验HelloWorld时,很好奇每个功用是怎样完成的,但是这个demo复用了许多功用、数据模型,刚开始理解起来就比较困难。所以我就先从功用点来看,将复用的功用、数据模型都剔除掉,确保单一功用能解藕独自运行。
环境
Xcode:15.1 beta
VisionOS:1.0
梳理功用
graph LR;
功用点-->A(设置光照);
style A fill:#bbf,color:#fff
click A "https://www.6hu.cc/post/7298690615046651943"
功用点-->B(手势滚动地球)
style B fill:#bbf,color:#fff
click B "https://www.6hu.cc/post/7298765809290706983"
功用点-->C(地球自转)
style C fill:#bbf,color:#fff
click C "https://www.6hu.cc/post/7298775642261569575"
功用点-->D(地球跟从鼠标拖动)
style D fill:#bbf,color:#fff
click D "https://www.6hu.cc/post/7299037876637351975"
功用点-->E(卫星围绕地球滚动)
style E fill:#bbf,color:#fff
click E "https://www.6hu.cc/post/7300431522255241250"
功用点-->G(沉溺式与窗口之间的切换)
style G fill:#bbf,color:#fff
click G "https://www.6hu.cc/spost/7300816733525901352"
沉溺式与窗口之间的切换
1. 翻开沉溺式空间
import SwiftUI
@main
struct MyWorldApp: App {
@State private var solarImmersionStyle: ImmersionStyle = .full
@State private var model = ViewModel()
var body: some Scene {
// 1.不带边框的window
WindowGroup{
SolarDisplayView()
.environment(model)
}
.windowStyle(.plain)
// 2.沉溺式空间
ImmersiveSpace(id: Module.solar.name) {
SolarView()
.environment(model)
}
.immersionStyle(selection: $solarImmersionStyle, in: .full)
}
// 3. 注册的Component、System
init() {
RotationComponent.registerComponent()
RotationSystem.registerSystem()
TraceComponent.registerComponent()
TraceSystem.registerSystem()
}
}
1.1 界说沉溺式空间
在翻开沉溺式空间之前,咱们需求界说一个沉溺式空间,在App
里边作为Scene
回来。
ImmersiveSpace(id: Module.solar.name) {
SolarView()
.environment(model)
}
1.2 翻开/封闭空间
// 翻开
@Environment(.openImmersiveSpace) private var openImmersiveSpace
Task {
await openImmersiveSpace(id: Module.solar.name)
}
// 封闭
@Environment(.dismissImmersiveSpace) private var dismissImmersiveSpace
Task {
await dismissImmersiveSpace()
}
留意: 咱们在翻开空间openImmersiveSpace
后,之前的window并不会消失,还会一向保存。也便是说,即便你进入了沉溺式空间后,之前的window也会进入沉溺式空间,同一时间会存在一个window、一个space。
为了更多会集在Space上面,咱们常常会对之前的window做一些躲藏、封闭等操作。
2.躲藏window
这儿的躲藏,便是改动原有Window的透明度,把无关的信息躲藏掉,看起来window就“消失”了,其实它并没有封闭。
WindowGroup{
SolarDisplayView()
.environment(model)
}
.windowStyle(.plain)
在躲藏之前,一定要设置.windowStyle(.plain)
,不然会一向显现毛玻璃窗口。
import SwiftUI
// 进入沉溺式空间的进口
struct SolarDisplayView: View {
@Environment(ViewModel.self) private var model
var body: some View {
ZStack {
// 退出沉溺式空间的开关
SolarSystemToggle()
.opacity(model.isShowingSolar ? 1 : 0)
VStack{
Text("进入沉溺式空间")
.font(.system(size: 50, weight: .bold))
.padding(.bottom, 15)
// 进入沉溺式空间的开关
SolarSystemToggle()
}
.opacity(model.isShowingSolar ? 0 : 1)
}
}
}
#Preview {
SolarDisplayView()
.environment(ViewModel())
}
这儿逻辑很简单,便是进入沉溺式空间前,显现进入开关。
进入沉溺式空间后,显现退出开关,其实是同一个window。
这儿会有几个疑问:
1. 为什么不直接封闭Window
@Environment(.dismissWindow) private var dismissWindow
Task {
await dismissWindow()
}
咱们确实能够先封闭window,然后再翻开window,但实际使用过程中会呈现闪烁的情况,所以才使用躲藏、显现。
2. 退出开关还能够怎样做?
能够直接放在Space空间,但是需求自己调整方位
能够用RealityView.attachment
,也需求调整方位
3. 为什么Space、window能够一同存在
我最开始会有这个疑问,为什么能一同存在,做成导航栈相同岂不是更好,一个翻开,另一个封闭。直到我看到Destination Video,我才知道它们一同存在的意义。里边展现一个视频播映的demo,最开始是一个视频列表窗口,有导航栈点击进入概况。概况展现了播映窗口,又展现了一个全景的沉溺式空间。在触摸这个demo之前,我一向认为播映器也在沉溺式空间里边,但是始终没有到达想要的效果,终究才发现window、space一同存在才干完成。
3.代码
进口是SolarDisplayView,MyWorldApp
发动进口也是它,直接Run
就能够。