[VisionOS] 拆分HelloWorld的功能点 - 地球跟随鼠标拖动

背景

在体验HelloWorld时,很好奇每个功能是怎么实现的,但是这个demo复用了很多功能、数据模型,刚开始理解起来就比较困难。所以我就先从功能点来看,将复用的功能、数据模型都剔除掉,保证单一功能能解藕单独运行。

环境

Xcode:15.1 beta

VisionOS:1.0

梳理功能

graph LR; 功能点-->A(设置光照); style A fill:#bbf,color:#fff click A "https://juejin.cn/post/7298690615046651943" 功能点-->B(手势转动地球) style B fill:#bbf,color:#fff click B "https://juejin.cn/post/7298765809290706983" 功能点-->C(地球自转) style C fill:#bbf,color:#fff click C "https://juejin.cn/post/7298775642261569575" 功能点-->D(地球跟随鼠标拖动) 功能点-->E(卫星围绕地球转动) 功能点-->F(月球围绕地球转动) 功能点-->G(沉浸式与窗口之间的切换)

地球跟随鼠标拖动

在这里可以明显看到窗口是有边界的,触碰到边界时,整个模型都很会切掉。如果我们在加载模型后,看不到效果,要考虑下是不是超出窗口了,适当的调整模型的位置,窗口的大小。

swift 复制代码
import SwiftUI
import RealityKit
import RealityKitContent

struct EarthPlacement: View {
    var body: some View {
        RealityView { content in
            guard let earth = await RealityKitContent.entity(named: "Globe") else {
                return
            }
            content.add(earth)
            earth.setSunlight(intensity: 14)

            earth.scale = SIMD3(repeating: 0.3)
        }
        .placementGestures(initialPosition: Point3D([450,300.0,100.0]))
    }
}

#Preview {
    EarthPlacement()
}

1. 加载3D资源

手势转动地球一样,资源必须要添加一个InputComponent,这样才可以添加手势。

2. 添加手势

swift 复制代码
import SwiftUI
import RealityKit

extension View {
    /// Listens for gestures and places an item based on those inputs.
    func placementGestures(
        initialPosition: Point3D = .zero,
        axZoomIn: Bool = false,
        axZoomOut: Bool = false
    ) -> some View {
        self.modifier(
            PlacementGesturesModifier(
                initialPosition: initialPosition,
                axZoomIn: axZoomIn,
                axZoomOut: axZoomOut
            )
        )
    }
}

/// A modifier that adds gestures and positioning to a view.
private struct PlacementGesturesModifier: ViewModifier {
    var initialPosition: Point3D
    var axZoomIn: Bool
    var axZoomOut: Bool

    @State private var scale: Double = 1
    @State private var startScale: Double? = nil
    @State private var position: Point3D = .zero
    @State private var startPosition: Point3D? = nil

    func body(content: Content) -> some View {
        content
            .onAppear {
                position = initialPosition
            }
            .scaleEffect(scale)
            .position(x: position.x, y: position.y)
            .offset(z: position.z)

            // Enable people to move the model anywhere in their space.
            .simultaneousGesture(DragGesture(minimumDistance: 0.0, coordinateSpace: .global)
                .handActivationBehavior(.pinch)
                .onChanged { value in
                    if let startPosition {
                        let delta = value.location3D - value.startLocation3D
                        position = startPosition + delta
                    } else {
                        startPosition = position
                    }
                }
                .onEnded { _ in
                    startPosition = nil
                }
            )

            // Enable people to scale the model within certain bounds.
            .simultaneousGesture(MagnifyGesture()
                .onChanged { value in
                    if let startScale {
                        scale = max(0.1, min(3, value.magnification * startScale))
                    } else {
                        startScale = scale
                    }
                }
                .onEnded { value in
                    startScale = scale
                }
            )
            .onChange(of: axZoomIn) {
                scale = max(0.1, min(3, scale + 0.2))
                startScale = scale
            }
            .onChange(of: axZoomOut) {
                scale = max(0.1, min(3, scale - 0.2))
                startScale = scale
            }
    }
}

手势转动地球类似,添加了DragGesture手势,在onChangedonEnded中改变positionMagnifyGesture放大手势,我暂时是没有用,模拟器也不知道怎么模拟。

相关推荐
杂雾无尘1 个月前
Vision Pro 新手教学:SwiftUI 实现 3D 应用的技巧,基础篇
ios·swiftui·visionos
HarderCoder1 年前
Apple Vision Pro 学习资料
visionos
苹果API搬运工1 年前
试玩 RealityComposerPro 中的 Shader Graph:用圆环制作一个 Meta Logo
visionos·增强现实
苹果API搬运工1 年前
我开源了个手势匹配框架,让你在模拟器调试 visionOS 手部追踪功能!
visionos·增强现实
苹果API搬运工1 年前
只需三板斧!带你入门 visionOS 空间计算的数学与几何基础
visionos·增强现实
-九月新辰-1 年前
Unity VisionOS开发流程
unity·游戏引擎·visionos
XR基地1 年前
XR 世界导览021 | AVP App Store上线网页版、如何在AVP上快速匹配手势、AVP开发岗位
visionos
XR基地2 年前
XR 世界导览#020-visionOS 1.1/Xcode 17.3/PICO 5.9.0 更新了!
unity3d·visionos
xChester2 年前
visionOS 应用图标设计
前端·ios·visionos
XR基地2 年前
XR 世界导览#019-Let's visionOS 大会/在 AVP 上玩手机或查看Spline的3D模型/用代码写ShaderGraph
unity3d·visionos