Three.js搭配OrbitControls.js实现flyTo()

Three.js搭配OrbitControls.js实现flyTo(),第1张

需求:较为简单,对3D场景进行OrbitControls自带的拖动缩放功能。在自写一个点击具体3D物体拉近相机的功能,也就是flyTo()。

flyTo()是一个动画过程,(想要线上了解效果的可以参考cesium的效果,链接地址 Cesium Sandcastle,我认识这个函数名也是在cesium中)

1.引入OrbitControls,这个步骤为简单,不在详细说明。我使用的是vue项目。

//在script中引入orbitcontrols

import {OrbitControls} from 'three/examples/jsm/controls/ObitControls.js';


//在初始化3D场景完成后创建控制对象

this.controls = new OrbitControls(this.camera,this.renderer.domElement);


至此,拖动和缩放功能应该没问题了。接下来实现flyTo()的功能。

2.flyTo()的实现。

思路:不断修改摄像头的位置和看的方向,最后聚焦于目标,涉及到 camera.position,camera.lookAt(),controls.target(不修改这个会出现一个小bug),不断修改使用tween.js。

菜全了开始动手。

// 引入,请写在正确的位置
import TWEEN from '@tweenjs/tween.js';


// 在变换之前使用一个全局变量记录过程值,
// 因为tween.js在update过程是修改参数的本身,不会返回新产生的return
// 如果只修改一个参数,例如positon,只需要将position传进去即可,
// 但是同时修改两个值,我的选择是将两个值组合在一块成为一个值
this.current = { 
    x:this.camera.position.x,
    y:this.camera.position.y,
    z:this.camera.position.z,
    x1:this.controls.target.x,
    y1:this.controls.target.y,
    z1:this.controls.target.z
 }
this.flyTo(this.getResultData(mesh))

// 计算出相机的目标位置和朝向 ,参数是被选中的物体
getResultData(mesh){
    let target = {
        x:mesh.position.x+300, //增加一些偏移量,使相机与目标物体之间有些距离,以便于观察
        y:mesh.position.y+300,
        z:mesh.position.z+150,
        x1:mesh.position.x,
        y1:mesh.position.y,
        z1:mesh.position.z
    }
    return target;

},
flyTo(target){
    this.tween = new TWEEN.tween(this.current);
    // 这一部分一定要加上,不然flyTo动作完成后,
    // 不论点击任何位置,controls都会将lootAt指向flyTo之前的位置
    // 将controls 的观察目标设置为选中物体
    this.tween.onComplete(()=>{
        let temp = new THREE.Vector3(target.x1,target.y1,target.z1);
        this.controls.target = temp;
    });
    // 每次更新相机位置和朝向
    this.onUpdate(()={
        this.camera.position = new THREE.Vector3(this.current.x,this.current.y,this.current.z);
        this.camera.lootAt(this.current.x1,this.current.y1,this.current.z1);
    });
    this.tween.to(target,500);
    this.tween.start();
},
// 在threejs的animate函数中添加

animate(){
    TWEEN.update();
},

到这里功能基本完成,但是会有一个问题,就是执行controls的拖动后,在放开鼠标之前鼠标移动到了可选的mesh上,那放开拖动鼠标,会立马执行一次点击的 *** 作,因为我flyTo()的触发事件就是click,所以算是很严重的问题。原因为拖动也是一次点击的过程。

解决思路:1、模式控制,拖动模式下取消click事件,需要flyTO()时设置controls.enable为false。2、修改controls源码,判断如果当次 *** 作为鼠标左键拖动则取消本次的flyTo()。

// 打开 three/examples/jsm/controls/ObitControls.js
// 在第40行增加 
this.stopClick = false; // 默认是可以clcik的
this.rotateCount = 0; // 记录本次拖动的持续时间,如果持续时间较短就认为是点击


// 在252行添加
scope.rotateCount ++;
if(scope.rotateCount>3){
    scope.stopClick = true;
}


// 在954行添加
if(scope.stopClick){
    setTimeout(()=>{
        scope.stopClick = false;
    },50);
}

然后再执行flyTO()之前判断controls.stopClick是否为真,如果是则直接返回。

代码全是手打,有可能存在打错的情况,请甄别。

Three.js搭配OrbitControls.js实现flyTo()_imcmuc的博客-CSDN博客需求:较为简单,对3D场景进行OrbitControls自带的拖动缩放功能。在自写一个点击具体3D物体拉近相机的功能,也就是flyTo()。flyTo()是一个动画过程,(想要线上了解效果的可以参考cesium的效果,链接地址Cesium Sandcastle,我认识这个函数名也是在cesium中)1.引入OrbitControls,这个步骤为简单,不在详细说明。我使用的是vue项目。//在script中引入orbitcontrolsimport {OrbitControls} from.https://blog.csdn.net/qq_38206656/article/details/123068682

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1299034.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存