问题描述
我开始关注几个 YouTube 教程,为初学者使用 Three.js。我看到其中一个示例创建了三个漂浮在空间中的球体并使它们可点击。
所以我按照教程设置了一个 Three.js 场景并创建了 6 个圆柱体的 3d 对象。我想要的是...
如果你点击一个物体,相机会指向并观察该物体,并且相机也会在该物体前面进行物理转换,所以我可以在那里显示文本或其他东西。到达那里后,我将限制控件,直到用户单击对象,然后补间将它们带回原始位置和方向。
我试图让逻辑是如果你点击对象1&&之前你没有点击它然后去看它,否则您单击对象 1 && 如果它已被单击,则相机将反向补间并返回原点... if else 您单击对象 2 && 您还没有单击它在然后去看它之前,否则如果你点击对象 2 && 如果它已经被点击....... 依此类推,直到每个对象的两个场景都被计算在内为了。我看到教程通过创建一个布尔变量将状态设置为已单击或未单击来对一个对象执行此操作。我试图将它合并到我的代码中,但我认为问题在于 Javascript 系统没有标记或保留将变量更改为一个或另一个的信息......这可能是一个语法错误,也可能是我采取的方法甚至不可能(未知的未知数),或者一个简单的错字。
一旦我对它们做了 5 个单独的 If 语句,那么我就能够看到每个补间按照我的意愿走向对象,但没有一个补间对检查它们是否已经被点击并将相机补间回到中心的部分。
这是我的代码,其中包含 5 个对象之一以供参考....
//ONE OF THE OBJECTS FOR REFERENCE
const minigeometry1 = new THREE.CylinderGeometry(5,5,0.5,50);
const minimaterial1 = new THREE.MeshStandardMaterial({ color: 0xffff00 });
const minicylinder1 = new THREE.Mesh(minigeometry1,minimaterial1);
minicylinder1.name = 'minicylinder1';
minicylinder1.position.z = 7.5;
minicylinder1.position.x = -28
minicylinder1.rotation.z = Math.PI / 2;
scene.add(minicylinder1);
//CLICK EVENT ANIMATIONS
//CAMERA MOVEMENT TWEEN FUNCTION//
function tweenCamera(finalPosition,tweenSpeed) {
let initialPosition = new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);
new TWEEN.Tween(initialPosition)
.to(finalPosition,tweenSpeed)
.onUpdate(() => {
camera.position.set(initialPosition.x,initialPosition.y,initialPosition.z);
})
.easing(TWEEN.Easing.Cubic.Out)
.start();
}
//WHERE THE CAMERA IS CURRENTLY LOOKING,I THINK
let currentTarget = new THREE.Vector3();
currentTarget.set(controls.target.x,controls.target.y,controls.target.z);
let originTarget = new THREE.Vector3();
originTarget.set(0,0);
//TELLS CAMERA TO ORIENT TOWARD SPECIFIED OBJECT (target controls = camera orientation?)
let minicylinder1Target = new THREE.Vector3();
minicylinder1Target.set(minicylinder1.position.x,minicylinder1.position.y,minicylinder1.position.z);
let minicylinder2Target = new THREE.Vector3();
minicylinder2Target.set(minicylinder2.position.x,minicylinder2.position.y,minicylinder2.position.z);
let minicylinder3Target = new THREE.Vector3();
minicylinder3Target.set(minicylinder3.position.x,minicylinder3.position.y,minicylinder3.position.z);
let minicylinder4Target = new THREE.Vector3();
minicylinder4Target.set(minicylinder4.position.x,minicylinder4.position.y,minicylinder4.position.z);
let minicylinder5Target = new THREE.Vector3();
minicylinder5Target.set(minicylinder4.position.x,minicylinder5.position.y,minicylinder5.position.z);
//RAYCASTER SETUP AND CLICK EVENT FUNCTION
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
function onClick(event) {
//normalized mouse coordinates (-1,+1)
mouse.x = (event.offsetX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse,camera);
const intersects = raycaster.intersectObjects(scene.children,true);
//THIS DETERmineS WHETHER WE HAVE CLICKED ON AN OBJECT OR NOT
let coin1Clicked = false;
let coin2Clicked = false;
let coin3Clicked = false;
let coin4Clicked = false;
let coin5Clicked = false;
//IF WE CLICK ON COIN1 FROM THE MAIN POSITION,WE WILL ZOOM INTO IT
if ((getIndexInIntersectsArray(minicylinder1,intersects) > -1) && !coin1Clicked) {
//TWEEN TO ORIENT CAMERA TOWARDS COIN1
new TWEEN.Tween(currentTarget)
.to(minicylinder1Target,2500)
.onUpdate(function() {
controls.target = currentTarget;
})
.easing(TWEEN.Easing.Quartic.InOut)
.start()
coin1Clicked = true;
//RESTRICT CAMERA ROTATION AND ZOOM OUT
tweenCamera(new THREE.Vector3(minicylinder1.position.x,25),2500)
return coin1Clicked;
} else if ((getIndexInIntersectsArray(minicylinder1,intersects) > -1) && coin1Clicked) {
//TWEEN TO ORIENT CAMERA TOWARDS COIN1
new TWEEN.Tween(currentTarget)
.to(originTarget,2500)
.onUpdate(function() {
controls.target = currentTarget;
})
.easing(TWEEN.Easing.Quartic.InOut)
.start()
coin1Clicked = false;
tweenCamera(new THREE.Vector3(origPos.position.x,origPos.position.y,origPos.position.z),2500);
return coin1Clicked;
}
if ((getIndexInIntersectsArray(minicylinder2,intersects) > -1) && !coin2Clicked) {
//TWEEN TO ORIENT CAMERA TOWARDS COIN1
new TWEEN.Tween(currentTarget)
.to(minicylinder2Target,2500)
.onUpdate(function() {
controls.target = currentTarget;
})
.easing(TWEEN.Easing.Quartic.InOut)
.start()
coin2Clicked = true;
//RESTRICT CAMERA ROTATION AND ZOOM OUT
tweenCamera(new THREE.Vector3(minicylinder2.position.x,2500)
return coin2Clicked;
}
if ((getIndexInIntersectsArray(minicylinder3,intersects) > -1) && !coin3Clicked) {
//TWEEN TO ORIENT CAMERA TOWARDS COIN1
new TWEEN.Tween(currentTarget)
.to(minicylinder3Target,2500)
.onUpdate(function() {
controls.target = currentTarget;
})
.easing(TWEEN.Easing.Quartic.InOut)
.start()
coin3Clicked = true;
//RESTRICT CAMERA ROTATION AND ZOOM OUT
tweenCamera(new THREE.Vector3(minicylinder3.position.x,2500)
return coin3Clicked;
}
if ((getIndexInIntersectsArray(minicylinder4,intersects) > -1) && !coin4Clicked) {
//TWEEN TO ORIENT CAMERA TOWARDS COIN1
new TWEEN.Tween(currentTarget)
.to(minicylinder4Target,2500)
.onUpdate(function() {
controls.target = currentTarget;
})
.easing(TWEEN.Easing.Quartic.InOut)
.start()
coin4Clicked = true;
//RESTRICT CAMERA ROTATION AND ZOOM OUT
tweenCamera(new THREE.Vector3(minicylinder4.position.x,2500)
return coin4Clicked;
}
if ((getIndexInIntersectsArray(minicylinder5,intersects) > -1) && !coin5Clicked) {
//TWEEN TO ORIENT CAMERA TOWARDS COIN1
new TWEEN.Tween(currentTarget)
.to(minicylinder5Target,2500)
.onUpdate(function() {
controls.target = currentTarget;
})
.easing(TWEEN.Easing.Quartic.InOut)
.start()
coin5Clicked = true;
//RESTRICT CAMERA ROTATION AND ZOOM OUT
tweenCamera(new THREE.Vector3(minicylinder5.position.x,2500)
return coin5Clicked;
}
}
function getIndexInIntersectsArray(elem,array) {
var ind = -1;
for (var i = 0; i < array.length; i++) {
if (array[i].object.name == elem.name) {
ind = i;
}
}
return ind;
}
window.addEventListener("click",(event) => {
onClick(event);
})
var animate = function() {
requestAnimationFrame(animate);
cylinder.rotation.y += 0.025;
minicylinder1.rotation.y += 0.025;
minicylinder2.rotation.y += 0.025;
minicylinder3.rotation.y += 0.025;
minicylinder4.rotation.y += 0.025;
minicylinder5.rotation.y += 0.025;
controls.update();
render();
TWEEN.update();
};
function render() {
renderer.render(scene,camera);
}
animate();
有人可以分享任何见解吗?请问漂亮吗? 提前致谢!
附言如果你觉得我的代码效率低下......我确定是这样,我想我可以使用 switch 语句,但我不知道该怎么做,因为这是我的第一个项目曾经做过所以我没有什么可以比较的。
解决方法
自我注意:在测试之后……处理/显示流程中的中断在哪里? (我想不出合适的词),通过将消息打印到控制台以查看我想要的/没有发生的事情,我意识到我必须把
让 coin1Clicked = false; . . . 让 coin5Clicked = false;
代码在我的 onClick 函数之外。我不知道为什么,因为我认为我将它们设为局部变量(与全局变量),这不应该是一个问题,至少我认为。一旦我将它们设为全局变量,if...else 语句就起作用了!进入 GSAP!