新闻详情

新闻详情

首页 / 资讯中心 / 详情

《HarmonyOS 7 ArkGraphics 3D 空间设计开发实战》05:Camera控制、手势映射与空间浏览交互【鸿蒙心迹】

发布时间:2026/11/15 12:57:48来源:尧图网络
《HarmonyOS 7 ArkGraphics 3D 空间设计开发实战》05:Camera控制、手势映射与空间浏览交互【鸿蒙心迹】
手指拖动200像素相机为什么不是在世界里移动200个单位前言前面四篇3D 房间已经能看了有家具、有材质、有灯光。但只能从一个固定视角看用户没法自己转一转、看一看。这一篇开始做交互单指拖动转视角双指缩放双指平移。看起来是很常见的手势但做起来有个很容易绕晕的问题ArkUI 手势给的是二维屏幕坐标像素单位。Camera 在三维世界里工作单位是世界坐标。手指拖动 200 像素不是相机在世界里移动 200 个单位——中间需要一层映射。很多人刚开始做的时候直接把手势 delta 加到相机位置上结果就是手指动一点相机飞出去十万八千里或者手指拖半天相机纹丝不动。这一篇就解决这个问题怎么把二维手势输入映射成三维空间里的相机旋转、缩放和平移。一、先搞清楚手势给的是什么相机需要的是什么先把两边的输入输出列清楚来源给的是什么单位ArkUI 手势手指在屏幕上移动了多少像素屏幕像素x, yCamera 需要的绕 Y 轴转了多少度Yaw、绕 X 轴转了多少度Pitch、离目标点多远Distance角度、世界单位这两个东西量纲都不一样不能直接加。需要一个转换系数屏幕上拖多少像素对应转多少度。举个例子如果用户手指在屏幕上从左到右拖满整个屏幕宽度比如 1080 像素我们希望相机正好绕 Y 轴转 360 度。那转换系数就是 360 / 1080 0.333 度每像素。也就是说手指拖 100 像素相机就转 33.3 度。这个系数不是固定的可以根据手感调整。有人喜欢灵敏一点有人喜欢稳一点。二、写一个 CameraController封装视角逻辑先写 CameraController把相机的状态和操作都封装进去import{scene}fromkit.ArkGraphics3DKit;exportclassCameraController{// 相机状态privateyaw:number0;// 绕Y轴旋转角度privatepitch:number-30;// 绕X轴俯仰角度privatedistance:number8;// 离目标点的距离privatetarget:{x:number,y:number,z:number}{x:0,y:0.5,z:0};// 观察目标点// 手势灵敏度privaterotateSensitivity:number0.3;// 每像素对应多少度privatezoomSensitivity:number0.01;// 每像素对应缩放多少privatecameraNode:scene.Node|nullnull;constructor(privatescene:scene.Scene){}/** * 初始化相机 */setupCamera():void{this.cameraNodethis.scene.createNode(MainCamera);constcamerathis.cameraNode.createComponent(scene.NodeComponentType.CAMERA)asscene.Camera;// 更新相机位置this.updateCameraTransform();this.scene.getRoot().addChild(this.cameraNode);console.info(CameraController: camera ready);}/** * 根据当前状态计算相机位置 */privateupdateCameraTransform():void{if(!this.cameraNode)return;// 球坐标转直角坐标根据yaw、pitch、distance算相机位置constradYawthis.yaw*Math.PI/180;constradPitchthis.pitch*Math.PI/180;constxthis.target.xthis.distance*Math.sin(radYaw)*Math.cos(radPitch);constythis.target.ythis.distance*Math.sin(radPitch);constzthis.target.zthis.distance*Math.cos(radYaw)*Math.cos(radPitch);this.cameraNode.position{x,y,z};// 相机始终看向目标点constcamerathis.cameraNode.getComponent(scene.NodeComponentType.CAMERA)asscene.Camera;camera.lookAtthis.target;}/** * 旋转视角单指拖动 */rotate(deltaX:number,deltaY:number):void{// deltaX 控制左右旋转yawthis.yawdeltaX*this.rotateSensitivity;// deltaY 控制上下俯仰pitchthis.pitchdeltaY*this.rotateSensitivity;// 限制俯仰角度不要转到天上或地下this.pitchMath.max(-80,Math.min(80,this.pitch));this.updateCameraTransform();}/** * 缩放双指捏合 */zoom(delta:number):void{this.distance-delta*this.zoomSensitivity;// 限制距离不要太近也不要太远this.distanceMath.max(2,Math.min(20,this.distance));this.updateCameraTransform();}}核心逻辑就在 updateCameraTransform() 里用 yaw左右角度、pitch俯仰角度、distance距离这三个参数算出相机在空间里的位置然后让相机看向目标点。这就是轨道相机Orbit Camera的基本模型相机绕着一个目标点转不是相机自己乱飞。三、把 ArkUI 手势接到 CameraController 上CameraController 写好了接下来接 ArkUI 的手势EntryComponentstruct SpaceRoomPage{privatecameraCtrl:CameraController|nullnull;build(){Stack(){scene.SceneView({scene:undefined}).width(100%).height(100%).gesture(// 单指拖动旋转PanGesture().onActionUpdate((event:GestureEvent){this.cameraCtrl?.rotate(event.offsetX,event.offsetY);})).gesture(// 双指捏合缩放PinchGesture().onActionUpdate((event:GestureEvent){// 双指距离变化来控制缩放this.cameraCtrl?.zoom(event.scale*10);}))}.width(100%).height(100%)}}这里有个坑PanGesture 的 event.offsetX 是本次手势开始到现在的总偏移不是每次回调的增量。也就是说手指从左边拖到右边拖了 500 像素第一次回调 offsetX 是 10第二次是 30第三次是 60……不是每次给你这次动了多少而是从手势开始到现在累计动了多少。所以正确的做法是记录上一次的位置每次算增量privatelastX:number0;privatelastY:number0;// onActionStart 的时候记录初始位置.onActionStart((){this.lastX0;this.lastY0;}).onActionUpdate((event:GestureEvent){// 本次增量 本次总偏移 - 上次总偏移constdeltaXevent.offsetX-this.lastX;constdeltaYevent.offsetY-this.lastY;this.cameraCtrl?.rotate(deltaX,deltaY);// 更新上次位置this.lastXevent.offsetX;this.lastYevent.offsetY;})这个坑特别常见。我第一次做的时候直接把 event.offsetX 加进去结果就是手指刚拖一下相机瞬间就转了 180 度因为 offsetX 是从手势开始累计的不是增量。四、加边界限制不要让相机穿墙开放的 3D 场景相机是可以随便跑的。但我们这个是房间内部相机不能穿墙不能转到房间外面去。两个限制俯仰角不要太极端不要转到天花板上面或者地板下面距离不要太近不要贴到家具里面刚才代码里已经加了// 限制俯仰角度在 -80 到 80 度之间this.pitchMath.max(-80,Math.min(80,this.pitch));// 限制距离在 2 到 20 之间this.distanceMath.max(2,Math.min(20,this.distance));这样用户再怎么拖相机也不会飞到离谱的位置。五、几个最容易踩的交互坑把这一篇遇到的坑总结一下坑现象解决办法手势坐标直接当世界坐标手指动一点相机飞出去加灵敏度系数像素转角度PanGesture 用了累计偏移不是增量刚开始拖一下相机转半圈记录上次位置每次算增量没有俯仰角限制相机转到天上或者地下pitch 限制在 -80 到 80 度没有距离限制缩放太近贴到模型里太远看不到distance 限制在 2 到 20拖动方向反了手指向右拖场景向左转deltaX 正负号调整一下手势太灵敏或者太迟钝手感不对调整 rotateSensitivity 参数这些问题都不是技术上做不到是手感调优。3D 交互的难点从来不是能不能转而是转起来是不是自然。总结第五篇的核心就一句话二维手势和三维相机之间必须有一层映射。ArkUI 手势给的是屏幕像素相机需要的是角度和距离不能直接加用轨道相机模型yaw左右转、pitch上下俯仰、distance距离三个参数控制相机PanGesture 给的是累计偏移要自己算每次的增量加边界限制俯仰角、距离都要有上下限不然相机乱飞灵敏度参数根据手感调没有标准答案SpaceRoom 现在用户可以自己转着看了。下一篇做更有意思的交互用户点一下沙发能选中它、移动它、删除它——也就是 3D 拾取。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/15 4:54:16

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/15 2:04:12

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/14 10:11:15

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/14 17:14:38

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/14 16:35:50

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/15 4:06:36

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉