removeEventListener 在 three.js 中的 if 语句中不起作用

removeEventListener isn't working inside my if statement in three.js

我是 JavaScript 的新手(但对数学(坐标系、三角学和 three.js 中涉及的其他一些东西)并不陌生)。我在 JavaScript 的代码学院学习了两个星期,我尝试按照 YouTube 上的教程在 three.js 中制作形状,以及当您单击鼠标或将鼠标悬停在目的。尽管我正在学习一个教程,但我必须观看 5 个关于同一主题的不同教程才能使其正常工作,但我仍然遇到问题。

我有 5 个对象,如果你将鼠标悬停在它们上面,它们会轻微旋转(比如 40 度,但这无关紧要),当你将鼠标移开对象时,它会稍微反向旋转回到起始位置。 如果我点击它们中的任何一个,我就会为相机移动一个靠近对象的补间。如果我再次单击同一个对象,它将补间相机回到场景开始时的位置。

我为 'mousemove' 和 'onclick' 创建了事件监听器,它们可以工作....但我想要的是,如果一个人点击了其中一个对象并且相机向它移动,我想删除悬停效果(然后如果他们再次单击该对象将使相机恢复原点,则一切恢复正常)。

目前我有一个关于 3D 对象的 raycaster 的 if 语句,所以我尝试在代码块中添加一行,当我点击一个对象时执行,因为那是我不希望事件监听器积极的。我尝试进行 google 搜索,浏览 Whosebug,观看更多 YouTube 视频,查看 MDN 网站,发现我完全按照说明进行操作(据我所知),但事实并非如此在职的。会不会是我什至没有考虑到的事情,比如不能在 if 语句或其他东西中删除事件监听器。

如果是这种情况,那么有没有一种方法可以禁用处理轻微旋转的补间,而仅在 if 语句的特定情况下?

我试图通过在我的 if 语句中添加一行来做到这一点,该语句在补间由点击事件触发但没有任何反应时执行。

//ONE OF THE OBJECTS FOR REFERENCE
const minigeometry1 = new THREE.CylinderGeometry(5, 5, 0.5, 50);
const minimaterial1 = new THREE.MeshLambertMaterial();
const minicylinder1 = new THREE.Mesh(minigeometry1, minimaterial1);
minicylinder1.name = 'minicylinder1';
minicylinder1.position.z = 7.5;
minicylinder1.position.x = -40;
minicylinder1.rotation.z = Math.PI / 2;
minicylinder1.rotation.y = Math.PI / 2;
scene.add(minicylinder1);

//TWEEN ANIMATIONS FOR CLICK EVENTS
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,0);

//TELLS CAMERA TO ORIENT TOWARD SPECIFIED OBJECT (target controls = camera orientation?)
let cylinderTarget = new THREE.Vector3();
cylinderTarget.set(cylinder.position.x, cylinder.position.y - 15, cylinder.position.z);
let minicylinder1Target = new THREE.Vector3();
minicylinder1Target.set(minicylinder1.position.x, minicylinder1.position.y, minicylinder1.position.z);

//THIS DETERMINES WHETHER WE ARE ZOOMING IN TO, OR OUT OF, OUR SELECTION
let coin1Clicked = false;
let coin2Clicked = false;
let coin3Clicked = false;
let coin4Clicked = false;

这是我的事件监听器.....

//THESE ARE AT THE BOTTOM OF MY CODE BUT THEY RUN WITHOUT ISSUE
window.addEventListener("click", (event) => {
    onClick(event);
})
window.addEventListener("mousemove", (event) => {
    onMouseMove(event);
})

这是我的 onClick 函数,下面是 onMouseMove 函数。你可以在这里看到,在我的 if 语句的第一个例子中,我尝试使用 removeEventListener(从这里往下 17 行),但没有用。

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);

    if ((getIndexInIntersectsArray(cylinder, intersects) > -1)) {
        window.open(cylinder.userData.URL);
    }

    //IF WE CLICK ON COIN1 FROM THE MAIN POSITION, WE WILL ZOOM INTO IT
    if ((getIndexInIntersectsArray(minicylinder1, intersects) > -1) && (!coin1Clicked)) {
        coin1Clicked = true;
        window.removeEventListener("mousemove", (event) => {
            onMouseMove(event);
        })
        //CODE THAT ACHIEVES MY SLIGHT ROTATION THAT I FOUND ON Whosebug
        var start = {}
        start.y = 0;
        var targ = {};
        targ.y = 0;

        function rot(s,t) {
            start["y"] = s;
            targ["y"] = t;
        }  
        rot(1.5*Math.PI/2, 4.5*Math.PI);
        const spun1 = new TWEEN.Tween(start).to(targ, 1500).onUpdate(function() {minicylinder1.rotation.y = start.y}).easing(TWEEN.Easing.Quintic.Out);
        spun1.start();
        new TWEEN.Tween(currentTarget)
            .to(minicylinder1Target, 2500)
            .onUpdate(function() {
                controls.target = currentTarget; 
            })
            .easing(TWEEN.Easing.Quartic.InOut)
            .start()
        //RESTRICT CAMERA ROTATION AND ZOOM OUT
        tweenCamera(new THREE.Vector3(minicylinder1.position.x, minicylinder1.position.y, 25), 2500)
        return coin1Clicked;
    } else if ((getIndexInIntersectsArray(minicylinder1, intersects) > -1) && (coin1Clicked)) {
        //TWEEN TO ORIENT CAMERA TOWARDS ORIGIN
        new TWEEN.Tween(currentTarget)
            .to(cylinderTarget, 2500)
            .onUpdate(function() {
                controls.target = currentTarget; 
            })
            .easing(TWEEN.Easing.Quartic.InOut)
            .start()
        coin1Clicked = false;
        //MOVES CAMERA BACK TO THE ORIGIN
        tweenCamera(new THREE.Vector3(minicylinder3.position.x, 20, 60), 2500)
        return coin1Clicked;
    } else if ((getIndex....................................

对象 2 到 4 相同


let coin1Hover = false;

function onMouseMove(event) {
    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);
    
    if ((getIndexInIntersectsArray(minicylinder1, intersects) > -1) && !coin1Hover) {
        coin1Hover = true;
        var start = {}
        start.y = 0;
        var targ = {};
        targ.y = 0;

        function rot(s,t) {
            start["y"] = s;
            targ["y"] = t;
        }  
        rot(Math.PI/2, 1.5*Math.PI/2);
        const spinning1 = new TWEEN.Tween(start).to(targ, 350).onUpdate(function() {minicylinder1.rotation.y = start.y});
        spinning1.start();
        return coin1Hover
    } else if ((getIndexInIntersectsArray(minicylinder1, intersects) > -1) && coin1Hover) {
        
    } else if ((getIndexInIntersectsArray(minicylinder1, intersects) == -1) && coin1Hover) {
        coin1Hover = false;
        var start = {}
        start.y = 0;
        var targ = {};
        targ.y = 0;

        function rot(s,t) {
            start["y"] = s;
            targ["y"] = t;
        }  
        rot(1.5*Math.PI/2, Math.PI/2);
        const backwards = new TWEEN.Tween(start).to(targ, 350).onUpdate(function() {minicylinder1.rotation.y = start.y});
        backwards.start();
        return coin1Hover
    }
    
    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("mousemove", (event) => {
    onMouseMove(event);
});

然后像这样删除它们:

window.removeEventListener("mousemove", (event) => {
    onMouseMove(event);
});

您必须知道,您将两个不同的匿名函数分配给两个方法调用。这样,就不可能移除正确的事件侦听器。请改用此模式:

window.addEventListener("mousemove", onMouseMove);

以后:

window.removeEventListener("mousemove", onMouseMove);