visionOS空间计算实战开发教程Day 6 拖拽和点击
在之前的学习中我们在空间中添加了3D模型,但在初始摆放后就无法再对其进行移动或做出修改。本节我们在Day 5显示和隐藏的基础上让我们模型可以实现拖拽效果,同时对纯色的立方体实现点击随机换色的功能。
首先是入口文件,无需做出改变,
import SwiftUI@main
struct visionOSDemoApp: App {var body: some Scene {WindowGroup() {ContentView()}ImmersiveSpace(id: "ImmersiveSpace") {ImmersiveView()}}
}
接着是ViewModel.swift文件,这里是核心逻辑:
import SwiftUI
import RealityKitclass ViewModel: ObservableObject {private var contentEntity = Entity()private let colors: [SimpleMaterial.Color] = [.gray, .red, .orange, .yellow, .green, .blue, .purple, .systemPink]func setupContentEntity() -> Entity {return contentEntity}func addCube() -> Entity {let entity = ModelEntity(mesh: .generateBox(size: 0.5, cornerRadius: 0),materials: [SimpleMaterial(color: .red, isMetallic: false)],collisionShape: .generateBox(size: SIMD3<Float>(repeating: 0.5)),mass: 0.0)entity.components.set(InputTargetComponent(allowedInputTypes: .indirect))entity.position = SIMD3(x: 0, y: 1, z: -2)contentEntity.addChild(entity)return entity}func changeToRandomColor(entity: Entity) {guard let _entity = entity as? ModelEntity else { return }_entity.model?.materials = [SimpleMaterial(color: colors.randomElement()!, isMetallic: false)]}
}
这里增加了一个colors常量,用于设置一个包含多种颜色数组,以便进行随机颜色修改。颜色是通过SimpleMaterial的color参数进行随机更换(randomElement),然后赋值给.materials属性,这部分逻辑位于changeToRandomColor中。
在addCube的逻辑中,我们还是常规地生成一个entity并返回。
接着来到ImmersiveView:
import SwiftUI
import RealityKitstruct ImmersiveView: View {@State var model = ViewModel()@State var cube = Entity()var body: some View {RealityView { content incontent.add(model.setupContentEntity())cube = model.addCube()}.gesture(DragGesture().targetedToEntity(cube).onChanged { value incube.position = value.convert(value.location3D, from: .local, to: cube.parent!)}).gesture(SpatialTapGesture().targetedToEntity(cube).onEnded { value inmodel.changeToRandomColor(entity: cube)})}
}
在这个视图中我们声明了cube变量,以便后续的拖拽和随机颜色修改操作。所以在初始化视图时将添加的立方体赋值给cube。然后分别通过DragGesture和SpatialTapGesture来实现拖拽和点击的逻辑。
这里需要说明一个本例中生成的立方体在完成拖放,隐藏后再次展开后会生成一个新的供拖放和修改颜色的模型,这时老的模型就无法再进行拖放了。如果读者只希望操作同一个模型,可以对addCube添加了一个name参数,并添加一个getTargetEntity方法来获取该对象,当然也可以通过预设名称来切换不同的模型进行操作,示例修改如下:
func getTargeEntity(name: String) -> Entity? {return contentEntity.children.first { $0.name == name }}func addCube(name: String) -> Entity {if let entity = getTargeEntity(name: name) {return entity}
...entity.name = name
...
对应的ImmersiveView也要修改为类似cube = model.addCube("Cube1")。
ContentView.swift的代码与Day 5一致:
import SwiftUI
import RealityKitstruct ContentView: View {@State var showImmsersiveSpace = false@Environment(\.openImmersiveSpace) var openImmersiveSpace@Environment(\.dismissImmersiveSpace) var dismissImmersiveSpacevar body: some View {NavigationStack {VStack {Toggle("Show ImmersiveSpace", isOn: $showImmsersiveSpace).toggleStyle(.button)}.padding()}.onChange(of: showImmsersiveSpace) { _, newValue inTask {if newValue {await openImmersiveSpace(id: "ImmersiveSpace")} else {await dismissImmersiveSpace()}}}}
}
运行应用点击盒子会随机改变颜色,拖拽盒子会跟随鼠标的位置移动。

示例代码:GitHub仓库
https://github.com/alanhou/ARDemo/tree/main/visionOS/Day6
其它相关内容请见虚拟现实(VR)/增强现实(AR)&visionOS开发学习笔记
https://alanhou.org/augmented-reality/
相关文章:
visionOS空间计算实战开发教程Day 6 拖拽和点击
在之前的学习中我们在空间中添加了3D模型,但在初始摆放后就无法再对其进行移动或做出修改。本节我们在Day 5显示和隐藏的基础上让我们模型可以实现拖拽效果,同时对纯色的立方体实现点击随机换色的功能。 首先是入口文件,无需做出改变…...
C# APS.NET CORE 6.0 WEB API IIS部署
1.创建 APS.NET CORE6.0 WEB API项目 默认选项即可 源代码: 项目文件展开: launchSettings.json {"$schema": "https://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication"…...
C/C++ 常用加密与解密算法
计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性,常常需要使用加密和解密算法。C是一种广泛使用的编程语言,提供了许多加密和解密算法的实现。本文将介绍一些在C中常用的加密与解密算法,这其中包括Xo…...
从Qt源码的角度分析Qt对象树与内存管理模式
作者:令狐掌门 技术交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ 文章目录 一、Qt对象树(Object Tree)和父子关系二、源码角度:QObject的内存管理构造函数析构函数addChild() 和 removeChild()三、C++模拟实现Qt的对象树内存管理模式Qt框架提供了一…...
MySQL与Redis如何保证数据的一致性
文章目录 MySQL与Redis如何保证数据的一致性?不好的方案1. 先写 MySQL,再写 Redis2. 先写 Redis,再写 MySQL3. 先删除 Redis,再写 MySQL 好的方案4. 先删除 Redis,再写 MySQL,再删除 Redis5. 先写 MySQL&am…...
micropython - espnow
espnow这个东西可以很简单的进行多设备近距离互联,连握手都不用注册一下就能发信息 目前8266那个8角的刷20231105的1M的固件可以运行 8266目前没有信号强度功能所以我自己写的类强度返回为0 我写的类实例化后最后注册谁发消息就是给谁而接收端则是什么都接ÿ…...
京东数据采集(京东数据运营):怎样快速获取京东市场大数据?
相信京东平台的很多品牌方们都有做数据分析的需求,但面对多而杂的市场数据,很多运营者都没有思路。单依靠肉眼来看,很多商品的类目、销售成绩、价格分布等运营者也未必清楚。 其实对于京东平台上市场数据的获取,品牌可以直接借助一…...
重生奇迹mu迷宫攻略
重生奇迹mu迷宫是一种比较有挑战性的游戏玩法,需要一定的技巧和策略才能完成。以下是一些基本的攻略和技巧: 了解每个迷宫的特点:不同的迷宫有不同的规则和特点,需要根据迷宫的特点来制定合理的策略。在进入迷宫前可以先了解一下…...
[网络] 4. HTTP/1.1 相比 HTTP/1.0 提高了什么性能?
HTTP/1.1 相比 HTTP/1.0 性能上的改进 ● 使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。 ● 支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减…...
3.1.2 Linux时间子系统 hrtimer示例使用
文章目录 结构体定义接口初始化启动修改取消示例示例1示例2示例3结构体定义 struct hrtimer {struct timerqueue_node node;ktime_t _softexpires;enum hrtimer_restart...
04 _ 系统设计目标(二):系统怎样做到高可用?
这里将探讨高并发系统设计的第二个目标——高可用性。 高可用性(High Availability,HA)是你在系统设计时经常会听到的一个名词,它指的是系统具备较高的无故障运行的能力。 我们在很多开源组件的文档中看到的HA方案就是提升组件可…...
Android相机性能提高50%
文章目录 应用举例(可以不看这一part,直接跳过看具体怎么做):Snapchat 通过 Camera2 Extensions API 将新相机功能的集成速度提高了 50%**Camera2 扩展 API 可以访问高级功能更多设备上的更多机会 正文:开始使用扩展架…...
STM32F103C8T6第5天:独立看门狗、窗口看门狗、dma实验
1. 独立看门狗IWDG介绍(341.45) 什么是看门狗? 在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断&#…...
QT已有项目导入工程时注意事项
文章目录 从qt其他版本上开发的工程导入另一qt版本时 从qt其他版本上开发的工程导入另一qt版本时 这里以之前在qt5.12.2上开发的项目为例,现在到在qt6.5.3上运行。 不能直接导入IDE上,否则会报各种莫名奇妙的错误。 首先要把扩展名位.pro.user文件 删掉…...
Django视图层
一、请求与响应 视图函数 视图函数,简称视图,属于Django的视图层,默认定义在views.py文件中,是用来处理web请求信息以及返回响应信息的函数,所以研究视图函数只需熟练掌握两个对象即可:请求对象(HttpRequ…...
我在electron中集成了自己的ai大模型
同学们可以私信我加入学习群! 正文开始 前言一、大模型选择二、获取key三、调用api四、调用ai模型api时,解决跨域总结 前言 最近单位把gpt、文心一言、通义千问、星火等等等等你能想到的ai大模型都给禁掉了,简直丧心病狂。 不知道有多少感同…...
oracle rac环境归档日志清除
文章目录 一、处理步骤1、使用终端登录上服务器查看磁盘使用状态2、使用恢复备份管理工具RMAN删除归档日志 二、详细操作步骤三、定时任务自动清归档日志1、编写删除脚本4、测试脚本运行情况5、设置定时任务每周执行一次,并测试运行效果 昨天单位的所有系统都连不上…...
【数据结构】树与二叉树(廿六):树删除指定结点及其子树(算法DS)
文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点4. 删除结点及其左右子树a. 逻辑删除与物理删除b. 算法DSTc. 算法解析d. 代码实现递归释放树算法DS e. 算法测试 5. 代码整合…...
交叉编译 和 软硬链接 的初识(面试重点)
目录 交叉编译的初认识Q&A Q1: 编译是什么? Q2: 交叉编译是什么? Q3: 为什么要交叉编译 Q3.1:树莓派相对于C51大得多,可以集成编译器比如gcc,那么树莓派就不需要交叉编译了吗? Q4: 什么是宿主机和…...
Docker attach 命令
docker attach:连接到正在运行中的容器。 语法 docker attach [OPTIONS] CONTAINER要attach上去的容器必须正在运行,可以同时连接上同一个container来共享屏幕(与screen命令的attach类似)。 官方文档中说attach后可以通过CTRL-…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
