首页 文章

Javascript鼠标事件不适用于Three.JS场景元素

提问于
浏览
0

好吧,我只是感到困惑(现在可能因为我自己的好事而太累了...) . 我正在尝试让我的three.js应用程序在鼠标悬停在场景中的特定类型的实体上时为不同的鼠标事件执行不同的功能 . “mousemove”类型的事件工作正常,而且

console.log( 'INTERSECTED.isGraphElement: ', INTERSECTED.isGraphElement, 'MouseEvent: ', mouse.type );

语句注册所有我发现 INTERSECTED.isGraphElement 对象的mouseEvents .

然而,当 transformGraphElement() 运行时,只有"mousemove"事件在 transformGraphElement 函数内注册 . 即使是在这里检测到的应该控制掉的代码的注释掉的测试行也会被检测到 .

我在 transformGraphElement 函数中尝试过的事情:

  • 为我正在侦听的其他类型之一交换dblclick事件 . 没有骰子 .

  • 注释掉处理mousemove事件的行 . 没有骰子 .

  • 测试我的 obj.referent.transformOnDblClick() 函数中是否有错误 . 我只知道它根本没有被调用(并且当我将它与"mousemove"事件关联时运行完美) .

  • 为我的'if'语句尝试不同的有效语法 . 没有骰子 .

  • 尝试对 mouseEventHandler() 函数进行一些重构 . 没有骰子 .

这是我的相关代码:

function render() {

        mouseEventHandler( transformGraphElement, unTransformGraphElement );

        requestAnimationFrame( render );
        renderer.render(scene, entities.cameras.perspCamera );
    }

    function mouseEventHandler( fn, revFn ){

        // update the picking ray with the camera and mouse position
        ray.setFromCamera( mouse, entities.cameras.perspCamera );

        // calculate objects intersecting the picking ray
        var intersects = ray.intersectObjects( scene.children );

        if ( intersects && intersects[0] && intersects[0].object ){

            if ( intersects[ 0 ].object != INTERSECTED ){   // if there's an intersected object

                if ( INTERSECTED ) {                        // and if a previous INTERSECTED object exists:
                    revFn( INTERSECTED, mouse );                    // restore the previous intersected object to its non-intersected state.                
                }                       

                INTERSECTED = intersects[ 0 ].object;       // set the currently intersected object to INTERSECTED
                fn( INTERSECTED, mouse );                           // transform the currentlY INTERSECTED object.

                }   

                console.log( 'INTERSECTED.isGraphElement: ', INTERSECTED.isGraphElement, 'MouseEvent: ', mouse.type );
            }
    }

    function transformGraphElement( obj, mouse ){

        // Check if INTERSECTED is a Graph Element, and if so, invoke it's transform function.  
        if ( mouse.type === "mousemove" && obj.isGraphElement ) { obj.referent.transformOnMouseOver(); }
        //if ( mouse.type === 'dblclick' ) { console.log('Got the dblclick Inside!') }  
        if ( mouse.type === 'dblclick' && obj.isGraphElement ) { obj.referent.transformOnDblClick(); ) }
    }

    function unTransformGraphElement( obj, mouse ){

        // Check if INTERSECTED is a Graph Element, and if so, revert it to it's pre-mouseEvent state.
        if ( mouse.type === "mousemove" && obj.isGraphElement ) { obj.referent.transformOnMouseOut(); }
        if ( mouse.type === 'dblclick' ) { console.log('Got the dblclick Out!') }
    }

我想知道它是否有某种默认行为或覆盖我正在遇到,但不应该event.preventDefault()行处理它? (以下代码在上面的代码之前运行):

var ray = new THREE.Raycaster();
    var mouse = new THREE.Vector2();
    var INTERSECTED;  // Object closest to the camera

    function onMouse( event ) {

        event.preventDefault();

        // calculate mouse position in normalized device coordinates
        // (-1 to +1) for both components

        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
        mouse.type = ( event.type );

    }

    function listenFor(){
        document.addEventListener( 'click', onMouse, false );
        document.addEventListener( 'mousemove', onMouse, false );
        document.addEventListener( 'mousedown', onMouse, false );
        document.addEventListener( 'dblclick', onMouse, false )
        document.addEventListener( 'wheel', onMouse, false );
        document.addEventListener( 'contextmenu', onMouse, false );
    }

    listenFor();

onMouse() 函数内部 Console.log( mouse.type ) 注册了我正在聆听的所有鼠标事件 .

我一直在撞击这个头3个小时 . 我希望这是一件很愚蠢的事,因为我心情不好,所以我很想念 . 我们欢迎所有的帮助,如果有任何遗漏的代码对提供有用的答案很重要,请告诉我......我不这么认为,但心情不好......

谢谢你的帮助!

1 回答

  • 0

    那么第二天早上我站起来找出问题所在 . 问题在于代码中的逻辑:

    if ( intersects[ 0 ].object != INTERSECTED ){   // if there's an intersected object
    
                    if ( INTERSECTED ) {                        // and if a previous INTERSECTED object exists:
                        revFn( INTERSECTED, mouse );                    // restore the previous intersected object to its non-intersected state.                
                    }                       
    
                    INTERSECTED = intersects[ 0 ].object;       // set the currently intersected object to INTERSECTED
                    fn( INTERSECTED, mouse );                           // transform the currentlY INTERSECTED object.
    
                    }   
    
                    console.log( 'INTERSECTED.isGraphElement: ', INTERSECTED.isGraphElement, 'MouseEvent: ', mouse.type );
                }
    

    无法传递非mousemove事件 . 我的解决方案是用另一个条件 if (mouse.type === 'mousemove') 包装此部分,然后为其他事件类型添加其他条件 . 这是整体,通过一些重构,使整体更容易推理:

    var ray = new THREE.Raycaster();
    var mouse = new THREE.Vector2();
    var INTERSECTED;  // Object closest to the camera
    
    function onMouse( event ) {
    
        event.preventDefault();
    
        // calculate mouse position in normalized device coordinates
        // (-1 to +1) for both components
    
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    
        mouseEventHandler( event /*, transformGraphElement, unTransformGraphElement */ );
    
    }
    
    function listenFor(){
        document.addEventListener( 'click', onMouse, false );
        document.addEventListener( 'mousemove', onMouse, false );
        document.addEventListener( 'mousedown', onMouse, false );
        document.addEventListener( 'dblclick', onMouse, false )
        document.addEventListener( 'wheel', onMouse, false );
        document.addEventListener( 'contextmenu', onMouse, false );
    }
    
    listenFor();
    
    /* ... */
    
    function render() {
    
        requestAnimationFrame( render );
        renderer.render(scene, entities.cameras.perspCamera );
    }
    
    function mouseEventHandler( event /* , fn, revFn */ ){
    
        // update the picking ray with the camera and mouse position
        ray.setFromCamera( mouse, entities.cameras.perspCamera );
    
        // calculate objects intersecting the picking ray
        var intersects = ray.intersectObjects( scene.children );
    
        // if there's at least one intersected object...
        if ( intersects && intersects[0] && intersects[0].object ){
    
            // Check if the event is a mouse move, INTERSECTED exists and we're sitting on the same INTERSECTED object as the last time this function ran...        
            if ( event.type === 'mousemove' ){
                // Check if the current top-level intersected object is the previous INTERSECTED        
                if ( intersects[ 0 ].object != INTERSECTED ){
                    // ... if there is a previous INTERSECTED
                    if ( INTERSECTED ) {    
                        // restore the previous INTERSECTED to it's previous state.
                        unTransformGraphElementOnMouseOut( INTERSECTED, event );                                    
                    }                       
                    // set the currently intersected object to INTERSECTED  
                    INTERSECTED = intersects[ 0 ].object;       
                    // and transform it accordingly.
                    transformGraphElementOnMouseOver( INTERSECTED, event );                         
                    }   
            }
    
            // Check if the mouse event is a doubble click 
            if ( event.type === 'dblclick' ){
                // If the currently intersected object is INTERSECTED
                if ( intersects[ 0 ].object === INTERSECTED ){
                    // select it.               
                    transformGraphElementOnSelect( INTERSECTED, event );                            
                }
                // If the currently intersected object is not INTERSECTED
                if ( intersects[ 0 ].object !== INTERSECTED ){
                    // If there is a previous INTERSECTED
                    if ( INTERSECTED )
                        // restore it to its unselected state.
                        unTransformGraphElementOnUnselect( INTERSECTED, event );                                
                }
            }       
    
        INTERSECTED && console.log( 'INTERSECTED.isGraphElement: ', INTERSECTED.isGraphElement, 'MouseEvent: ', event.type );           
        }
    }
    
    function transformGraphElementOnMouseOver( obj, event ){
        if ( obj.isGraphElement ) { obj.referent.transformOnMouseOver(); }  
    }
    
    function unTransformGraphElementOnMouseOut( obj, event ){
        if ( obj.isGraphElement ) { obj.referent.transformOnMouseOut(); }
    }
    
    function transformGraphElementOnSelect( obj, event ){
        if ( obj.isGraphElement ) { obj.referent.transformOnDblClick(); }   
    }
    
    function unTransformGraphElementOnUnselect( obj, event ){
        if ( obj.isGraphElement ) { obj.referent.unTransformOnDblClick(); } 
    }
    

    mouseEventHandler() 的逻辑仍有一些问题,但核心挫折得到了解决 . 一些额外的重构值得一提:

    • 没有必要将 event.type 添加到 mouse .

    • 我将 mouseEventHandler() 呼叫从 render() 移至 onMouse() . 这确保了鼠标事件只被注册一次 .

    • 我摆脱了 mouseEventHandler() 中的'fn' / 'revFn'回调,因为他们只是让事情变得比他们需要的更令人困惑 .

    • Event 不会't need to be a parameter for the transform functions, that'很快就要出来了 .

    希望这有助于某人 .

相关问题