155. TWEEN.JS点按钮,相机飞行靠近观察设备

server/2024/12/2 7:00:00/

实际开发的的时候,一个较大的三维场景,有很多不同的设备或物品,你可能希望通过UI按钮点击切换到不同视角,观察某个区域,或者说放大观察某个特定的物品或设备。

按钮

切换相机位置和视角的按钮

javascript"><div class="pos"><div id="A" class="bu">设备A</div><div id="B" class="bu" style="margin-left: 10px;">设备B</div><div id="car" class="bu" style="margin-left: 10px;">停车场</div><div id="all" class="bu" style="margin-left: 10px;">整体</div>
</div>

点击按钮A,相机运动到设备A附近

点击按钮A,相机运动到工厂中设备A附近,同时把相机观察目标,逐渐切换到设备A

javascript">import TWEEN from '@tweenjs/tween.js';
function render() {TWEEN.update();requestAnimationFrame(render);
}
render();

如果你希望相机移动到场景中某个位置附近,可以在Blender三维建模中,创建一个空对象进行标注,本节课模型用的是原来标注标签的空对象。当然你也可以直接读取某个模型的世界坐标。

获取某个对象世界坐标,作为相机lookAt指向的新目标观察点。

javascript">const A = model.getObjectByName('设备A标注');
const pos = new THREE.Vector3();
//获取三维场景中某个对象世界坐标
A.getWorldPosition(pos);

相机位置相对目标观察点,适当偏移,希望观察的范围大,就距离远一点,希望观察的设备显示效果大,就距离设备近一点。

javascript">// 向量的x、y、z坐标分别在pos基础上增加30
const pos2 = pos.clone().addScalar(30);

相机的位置逐渐改变,相机的观察目标也逐渐改变。

javascript">// 切换到设备A预览状态
document.getElementById('A').addEventListener('click', function () {const A = model.getObjectByName('设备A标注');const pos = new THREE.Vector3();A.getWorldPosition(pos); //获取三维场景中某个对象世界坐标// 相机飞行到的位置和观察目标拉开一定的距离const pos2 = pos.clone().addScalar(30);//向量的x、y、z坐标分别在pos基础上增加30// 相机从当前位置camera.position飞行三维场景中某个世界坐标附近new TWEEN.Tween({// 相机开始坐标x: camera.position.x,y: camera.position.y,z: camera.position.z,// 相机开始指向的目标观察点tx: 0,ty: 0,tz: 0,}).to({// 相机结束坐标x: pos2.x,y: pos2.y,z: pos2.z,// 相机结束指向的目标观察点tx: pos.x,ty: pos.y,tz: pos.z,}, 2000).onUpdate(function (obj) {// 动态改变相机位置camera.position.set(obj.x, obj.y, obj.z);// 动态计算相机视线camera.lookAt(obj.tx, obj.ty, obj.tz);}).start();
})

考虑OrbitControls的影响

如果你在项目中使用了相机控件OrbitControls,希望相机looAt()指向的目标改变以后,该相机控件让然可以正常使用。需要在动画结束.onComplete()的时候重新设置controls.target,或者.onUpdate()更新controls.target

javascript">.onUpdate(function (obj) {...camera.lookAt(obj.tx, obj.ty, obj.tz);
})
.onComplete(function(obj){controls.target.set(obj.tx, obj.ty, obj.tz);controls.update();
})

或者.onUpdate()中,设置controls.target,并执行controls.update()OrbitControls相机控件内部也会执行相机的.looAt()方法,完整相机视线重新计算,这样就不用执行camera.lookAt(obj.tx, obj.ty, obj.tz)

实际开发,相机目标观察点初始状态,不一定就是坐标原点,再设置动画初始目标观察点的时候,可以直接访问controls.target的x、y、z属性获取。

javascript">.onUpdate(function (obj) {// 动态改变相机位置camera.position.set(obj.x, obj.y, obj.z);// 动态计算相机视线// camera.lookAt(obj.tx, obj.ty, obj.tz);controls.target.set(obj.tx, obj.ty, obj.tz);controls.update();
})

封装一个相机动画函数

这样所有的按钮点击后,都可以调用该函数。

动画开始的相机位置和目标观察点,不要手写具体数字,通过相机对象camera.position和相机控件对象读取controls.target,这样不管你点击那个按钮,动画开始状态都是上次相机动画结束的状态。

javascript">// 相机动画函数,从A点飞行到B点,A点表示相机当前所处状态
// pos: 三维向量Vector3,表示动画结束相机位置
// target: 三维向量Vector3,表示相机动画结束lookAt指向的目标观察点
function createCameraTween(endPos,endTarget){new TWEEN.Tween({// 不管相机此刻处于什么状态,直接读取当前的位置和目标观察点x: camera.position.x,y: camera.position.y,z: camera.position.z,tx: controls.target.x,ty: controls.target.y,tz: controls.target.z,}).to({// 动画结束相机位置坐标x: endPos.x,y: endPos.y,z: endPos.z,// 动画结束相机指向的目标观察点tx: endTarget.x,ty: endTarget.y,tz: endTarget.z,}, 2000).onUpdate(function (obj) {// 动态改变相机位置camera.position.set(obj.x, obj.y, obj.z);// 动态计算相机视线// camera.lookAt(obj.tx, obj.ty, obj.tz);controls.target.set(obj.tx, obj.ty, obj.tz);controls.update();//内部会执行.lookAt()}).start();
}

设置设备A、设备B、停车场、整体预览四个按钮对应的相机动画,这样你可以在4个按钮之间,随意切换相机的观察状态。

javascript">// 切换到设备A预览状态
document.getElementById('A').addEventListener('click', function () {const A = model.getObjectByName('设备A标注');const pos = new THREE.Vector3();A.getWorldPosition(pos); //获取三维场景中某个对象世界坐标// 相机飞行到的位置和观察目标拉开一定的距离const pos2 = pos.clone().addScalar(30);createCameraTween(pos2, controls.target)
})
// 切换到设备B的预览状态
document.getElementById('B').addEventListener('click', function () {const B = model.getObjectByName('设备B标注');const pos = new THREE.Vector3();B.getWorldPosition(pos); //获取三维场景中某个对象世界坐标// 相机飞行到的位置和观察目标拉开一定的距离const pos2 = pos.clone().addScalar(30);// 相机从当前位置camera.position飞行三维场景中某个世界坐标附近createCameraTween(pos2, controls.target)
})// 切换到设备停车场的预览状态
document.getElementById('car').addEventListener('click', function () {const car = model.getObjectByName('停车场标注');const pos = new THREE.Vector3();car.getWorldPosition(pos); //获取三维场景中某个对象世界坐标// 相机飞行到的位置和观察目标拉开一定的距离const pos2 = pos.clone().addScalar(30);// 相机从当前位置camera.position飞行三维场景中某个世界坐标附近createCameraTween(pos2, pos)
})// 相机整体预览对应的位置和观察目标
const cameraPos0 = new THREE.Vector3(202, 123, 125) 
const target0 = new THREE.Vector3(0, 0, 0);
// 切换整体预览状态
document.getElementById('all').addEventListener('click', function () {// 相机从当前位置camera.position回到整体预览状态createCameraTween(cameraPos0, target0)
})

http://www.ppmy.cn/server/146643.html

相关文章

queue 和 Stack

import scala.collection.mutable //queue:队列.排队打饭.... //特点&#xff1a;先进先出 //Stack:栈 //特点&#xff1a;先进后出 class ob5 { def main(args: Array[String]): Unit { val q1 mutable.Queue(1) q1.enqueue(2)//入队 q1.enqueue(3)//入队 q1.enqueue(4)…

技术文档创作指南:打造卓越专业精准蓝图之道

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

网络安全中级试题

中级选择题 什么是DDoS攻击的主要目标&#xff1f; A. 窃取敏感数据 B. 禁止用户访问目标系统 C. 恶意软件传播 D. 伪装身份进行欺诈 在网络安全中&#xff0c;"端口扫描"通常用于什么目的&#xff1f; A. 查找系统漏洞 B. 提高网络速度 C. 加密通信 D. 防火墙配置…

vue3中是如何实现双向数据绑定的

在 Vue 3 中&#xff0c;双向数据绑定主要通过 v-model 指令实现。v-model 是一个语法糖&#xff0c;它内部实际上结合了 v-bind 和 v-on 指令来实现数据的双向绑定。下面详细介绍 Vue 3 中双向数据绑定的实现原理和使用方法。 双向数据绑定的基本原理 v-bind 指令&#xff1…

小程序-基于java+SpringBoot+Vue的戏曲文化苑小程序设计与实现

项目运行 1.运行环境&#xff1a;最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境&#xff1a;IDEA&#xff0c;Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境&#xff1a;Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…

【人工智能】用Python和Scikit-learn构建集成学习模型:提升分类性能

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 集成学习(Ensemble Learning)是通过组合多个弱学习器提升模型性能的机器学习方法,广泛应用于分类、回归及其他复杂任务中。随机森林(Random Forest)和梯度提升(Gradient Boosting)是集成学习的两种…

智能化图书馆导航系统方案之系统架构与核心功能设计

hello~这里是维小帮&#xff0c;点击文章最下方获取图书馆导航系统解决方案&#xff01;如有项目需求和技术交流欢迎大家私聊我们~撒花&#xff01; 针对传统图书馆在图书查找困难、座位紧张、空间导航不便方面的问题&#xff0c;本文深入剖析了基于高精度定位、3D建模、图书搜…

【测试工具JMeter篇】JMeter性能测试入门级教程(四):JMeter中BeanShell内置方法使用

一、什么是BeanShell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;BeanShell是一种松散类型的脚本语言(这点和JS类似);BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性,非常精简…