英文:
Adding point-and-click navigation to a three.js project where OrbitControls is enabled
问题
我在three.js中正在制作一个带有点-and-click导航功能的导航测试。
这个问题出在当与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;
}
});
};
我确信这会起作用,而且确实有点作用,但相机在动画结束时有点颤动,好像我分配的新目标不太正确:
如果你仔细观察GIF,可以看到动画末尾,相机会颤动一下。有时它非常明显,有时它只是一个小的移动。
我不知道是什么原因导致这个问题,我的目标是使相机的旋转在动画之前和之后保持相同,所以我认为如果我通过与相机本身相同的量来偏移相机的目标,它应该会起作用,但显然没有。
有人可以帮助我解决这个问题吗?
如果你想尝试并看看我是什么意思,我在这个GitHub仓库中上传了项目。完整的js文件在这里。
提前感谢你。
英文:
I am making a navigation test in three.js with a point-and-click navigation functionality.
The point-and-click mechanic is really simple : a raycaster determines the point in the plane where the user clicked and I move the camera there with gsap
:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const move_cam = () => {
const new_pos = { ...marker.position };
gsap.to(camera.position, {
duration: 2,
x: new_pos.x,
z: new_pos.z,
onComplete: () => {
}
});
};
<!-- end snippet -->
The problem with this is that, when used along with OrbitControls, the camera moves while always pointing to the same place :
The reason is that OrbitControls gives a target to the camera to keep looking at, allowing it to "orbit".
My first attempt was just to disable OrbitControls during the camera movement with controls.enabled= false
and reenabling it after the fact with the callback function onComplete()
of gsap
but it doesn't work since controls.enabled= false
only disables the interaction with the user but it doesn't keep the camera from looking at its target.
I also thought about preventing OrbitControls to affect the camera during the movement by adding a condition to the animation loop :
if (!camera_is_moving) {
controls.update();
}
But the camera goes back to looking at the target as soon as the animation is finished.
As a last ressort, I decided to store the distance of the camera to its target in an variable called offset
and then using that offset to define a new target at the end of the animation. And the move_cam()
function ended up like this :
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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;
}
});
};
<!-- end snippet -->
I was sure it would work and I kind of did but the camera kind of twitches at the end of the animation as if the new target I assigned was not quite the correct one :
If you look closely at the gif, right at the end of the animation, the camera stutters a bit. Sometimes it's very significant and sometimes it's just a small movement.
I don't know what's causing this, my objective is that the camera's rotation stays the same as before the animation so I thought that if I offset the camera's target by the same amount as the camera itself, it would work but apparently, it didn't.
Can anyone help me with this?
I uploaded the project in this Github repo if you want to try and see what I mean.
The full js file is here.
Thank you in advance.
答案1
得分: 0
我通过使用gsap单独为摄像机目标设置动画来解决了这个问题,而不是在onComplete()
回调中设置其值,因此move_cam()
函数最终如下:
英文:
I managed to solve it by animating the camera target separately with gsap instead of setting its value in the onComplete()
callback so the move_cam()
function ended up like this :
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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,
});
};
<!-- end snippet -->
I solves my problem completely but I still don't know why the previous code didn't work.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论