简体   繁体   English

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

[英]Javascript Mouse Events Not Working on Three.JS Scene Elements

Ok, I'm just confused (and probably too tired for my own good to be working on this now...). 好的,我只是感到困惑(可能为了我自己的利益而太累了,现在就不能从事此工作了……)。 I'm trying to get my three.js application to execute different functions for different mouse events when the mouse is over a particular type of entity in my scene. 我试图让我的three.js应用程序在鼠标悬停在场景中特定类型的实体上时针对不同的鼠标事件执行不同的功能。 Events of type "mousemove" are working perfectly, and the 类型为“ mousemove”的事件可以正常运行,并且

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

statement registers all the mouseEvents that I'm listening for, which include "mousemove", "click", "dblclick", "wheel" and "oncontextmenu". 语句记录了我正在侦听的所有mouseEvent,包括“ mousemove”,“ click”,“ dblclick”,“ wheel”和“ oncontextmenu”。 It's also detecting INTERSECTED.isGraphElement objects as intented. 它还检测INTERSECTED.isGraphElement对象。

Nevertheless, when transformGraphElement() runs, only the "mousemove" events are registered inside the transformGraphElement function. 但是,运行transformGraphElement() ,只有“ mousemove”事件会在transformGraphElement函数内部注册。 Even the commented-out test line of code that should console out "Got the dblclick!" 甚至应该注释掉测试行的代码,也请放心“让dblclick!” doesn't run. 不运行。 It appears that no other mouse events that I'm listening for are being detected here. 似乎这里没有检测到我正在监听的其他鼠标事件。

Things I've tried inside the transformGraphElement function: 我在transformGraphElement函数中尝试过的事情:

  • Swap out the dblclick event for one of the other types I'm listening for. 将dblclick事件换成我正在侦听的其他类型之一。 No dice. 没有骰子。
  • Comment out the line for handling mousemove events. 注释掉用于处理mousemove事件的行。 No dice. 没有骰子。
  • Test to see if there's a bug in my obj.referent.transformOnDblClick() function. 测试以查看我的obj.referent.transformOnDblClick()函数中是否存在错误。 I only learned that it wasn't being called at all (and runs perfectly when I associate it to the "mousemove" event). 我仅了解到根本没有调用它(并且当我将其与“ mousemove”事件相关联时,它可以完美运行)。
  • Trying different valid syntaxes for my 'if' statements. 为我的'if'语句尝试不同的有效语法。 No dice. 没有骰子。
  • Trying a bit of refactoring on the mouseEventHandler() function. 尝试对mouseEventHandler()函数进行一些重构。 No dice. 没有骰子。

Here's my relevant code: 这是我的相关代码:

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!') }
    }

I'm wondering if its some sort of default behavior or override that I'm running into, but shouldn't the event.preventDefault() line be handling that? 我想知道它是否是某种默认行为或我正在遇到的替代,但是event.preventDefault()行是否应该处理该行为? (This code below runs before the code above): (下面的代码在上面的代码之前运行):

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 ) from inside the onMouse() function registers all the mouse events I'm listening for perfectly. onMouse()函数内部的Console.log( mouse.type )注册了我正在完美监听的所有鼠标事件。

I've been banging my head against this for 3 hours. 我已经为此奋斗了3个小时。 I'm hoping it's something stupid simple that I'm missing because I'm in a bad mood. 我希望这是一个愚蠢的简单事情,我因为心情不好而错过了。 All help is welcome, and let me know if there's any missing code important to providing a useful answer... I don't think so but again, in a bad mood... 欢迎所有帮助,让我知道是否有缺少的代码对于提供有用的答案很重要...我不这么认为,但心情不好...

Thanks for your help! 谢谢你的帮助!

Well the next morning I got up and figured out the problem. 好吧,第二天早上,我起床,找出了问题所在。 The issue was with the logic in the code: 问题出在代码中的逻辑上:

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

Non-mousemove events could not be passed. 无法传递非ousemove事件。 My solution was to wrap this section with another conditional if (mouse.type === 'mousemove') and then have additional conditionals for other event types. 我的解决方案是用另一个条件if (mouse.type === 'mousemove')包装本节,然后为其他事件类型提供附加条件。 Here's the whole, with a bit of refactoring to make the whole easier to reason about: 这是整体,并进行了一些重构以使整体更易于推理:

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

The logic of mouseEventHandler() still has some issues, but the core frustration is handled. mouseEventHandler()的逻辑仍然存在一些问题,但是可以解决核心挫败感。 Some additional refactoring worth mentioning: 值得一提的一些其他重构:

  • It wasn't necessary to add the event.type to mouse . 无需将event.type添加到mouse
  • I moved the mouseEventHandler() call from render() to onMouse() . 我将mouseEventHandler()调用从render()移到了onMouse() That ensures that mouse events are registered only once. 这样可以确保鼠标事件仅注册一次。
  • I got rid of the 'fn'/'revFn' callbacks in mouseEventHandler() as they just made things more confusing than they need to be. 我摆脱了mouseEventHandler()中的'fn'/'revFn'回调,因为它们使事情变得比需要的更加混乱。
  • Event doesn't need to be a parameter for the transform functions, that'll be coming out shortly. Event不必是转换函数的参数,它很快就会出现。

Hope this helps someone. 希望这对某人有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM