javascript 向启用了OrbitControls的three.js项目添加点击导航

w46czmvw  于 2023-03-21  发布在  Java
关注(0)|答案(1)|浏览(144)

我正在用three.js做一个navigation test,带有点击导航功能。
点击机制非常简单:raycaster确定用户单击的平面中的点,我将相机移动到那里gsap

const move_cam = () => {
    const new_pos = { ...marker.position };
    gsap.to(camera.position, {
      duration: 2,
      x: new_pos.x,
      z: new_pos.z,

      onComplete: () => {
      }
    });
  };

这样做的问题是,当与OrbitControls沿着使用时,摄影机移动时总是指向同一个地方:

原因是OrbitControls为相机提供了一个目标,让它继续观察,允许它“环绕”。
我的第一次尝试只是在相机移动期间使用controls.enabled= false禁用OrbitControls,并在事后使用gsap的回调函数onComplete()重新启用它,但它不起作用,因为controls.enabled= false仅禁用与用户的交互,但它不会阻止相机查看其目标。
我还考虑过通过在动画循环中添加一个条件来防止OrbitControls在移动过程中影响摄影机:

if (!camera_is_moving) {
controls.update();
}

但动画一结束,摄影机就会返回到目标。
作为最后一次重新排序,我决定将相机到其目标的距离存储在一个名为offset的变量中,然后使用该偏移量在动画结束时定义一个新的目标。move_cam()函数最终如下所示:

const move_cam = () => {
    camera_is_moving = true;
    const offset = {
      x: controls.target.x - camera.position.x,
      y: controls.target.y - camera.position.y,
      z: controls.target.z - camera.position.z,
    };

    const new_pos = { ...marker.position };
    new_pos.y = CAMERA_HEIGHT;
    
    gsap.to(camera.position, {
      duration: 2,
      x: new_pos.x,
      y: new_pos.y,
      z: new_pos.z,

      onComplete: () => {
        controls.target.x = offset.x + camera.position.x;
        // controls.target.y= offset.x + camera.position.y;
        controls.target.z = offset.x + camera.position.z;

        offset.x = controls.target.x - camera.position.x;
        offset.y = controls.target.y - camera.position.y;
        offset.z = controls.target.z - camera.position.z;
        camera_is_moving = false;
      }

    });
  };

我确信它会起作用,我也确实做到了,但在动画结束时,相机有点抽搐,好像我分配的新目标并不完全正确:

如果你仔细看动图,就在动画的最后,摄像机会有一点卡顿,有时很明显,有时只是一个小动作。
我不知道是什么原因造成的,我的目标是相机的旋转保持与动画之前相同,所以我认为如果我偏移相机的目标与相机本身相同,它会工作,但显然,它没有。
有人能帮我吗?
我上传了这个项目在这个Github repo如果你想尝试和明白我的意思。完整的js文件是here
先谢谢你。

2fjabf4q

2fjabf4q1#

我设法解决了这个问题,方法是用gsap单独为相机目标设置动画,而不是在onComplete()回调中设置其值,因此move_cam()函数的结果如下:

const move_cam = () => {
    camera_is_moving = true;
    controls.enabled = false;
    const offset = {
      x: controls.target.x - camera.position.x,
      y: controls.target.y - camera.position.y,
      z: controls.target.z - camera.position.z,
    };
    const new_pos = { ...marker.position };
    new_pos.y = camera.position.y;

    gsap.to(this.camera.position, {
      duration: this.camera_travel_duration,
      x: new_pos.x,
      y: new_pos.y,
      z: new_pos.z,

      onComplete: () => {
        offset.x = controls.target.x - camera.position.x;
        offset.y = controls.target.y - camera.position.y;
        offset.z = controls.target.z - camera.position.z;

        camera_is_moving = false;
        controls.enabled = true;
      },
    });
    gsap.to(controls.target, {
      duration: camera_travel_duration,
      x: offset.x + new_pos.x,
      z: offset.z + new_pos.z,
    });
  };

我完全解决了我的问题,但我仍然不知道为什么以前的代码不工作。

相关问题