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

问题描述 投票:0回答:1

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

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

语句记录我正在侦听的所有mouseEvent,包括“mousemove”,“click”,“dblclick”,“wheel”和“oncontextmenu”。它还检测INTERSECTED.isGraphElement对象的意图。

然而,当transformGraphElement()运行时,只有“mousemove”事件被记录在transformGraphElement函数内。即使是注释掉的测试代码行,也应该控制掉“得到dblclick!”不运行。似乎在这里没有检测到我正在侦听的其他鼠标事件。

我在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();

来自Console.log( mouse.type )函数内部的onMouse()记录了我正在聆听的所有鼠标事件。

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

谢谢你的帮助!

javascript events three.js mouseevent mouse
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不需要成为变换函数的参数,很快就会出现。

希望这有助于某人。

© www.soinside.com 2019 - 2024. All rights reserved.