好吧,我只是感到困惑(现在可能因为我自己的好事而太累了...)。我正在尝试让我的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
函数中尝试过的事情:
obj.referent.transformOnDblClick()
函数中是否存在错误。我只知道它根本没有被调用(当我将它与“mousemove”事件联系起来时运行完美)。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个小时。我希望这是一件很愚蠢的事,因为我心情不好,所以我很想念。我们欢迎所有的帮助,如果有任何遗漏的代码对提供有用的答案很重要,请告诉我......我不这么认为,但心情不好......
谢谢你的帮助!
那么第二天早上我站起来找出问题所在。问题在于代码中的逻辑:
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
不需要成为变换函数的参数,很快就会出现。希望这有助于某人。