THREE.js射线相交失败通过添加div

如果页面上只有一个目标div(其中包含renderer.domElement),则Three.js脚本运行良好。 只要我在目标div上方添加具有固定高度和宽度的另一个div,ray.intersectObjects就会返回null。 我怀疑我为ray创build的vector是造成这个问题的原因。 这是代码。

var vector = new THREE.Vector3( ( event.clientX / divWidth ) * 2 - 1, -( event.clientY / divHeight ) * 2 + 1, 0.5 ); projector.unprojectVector( vector, camera ); var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() ); var intersects = ray.intersectObjects( myObjects, true ); 

任何想法如何我可以解决这个问题。

编辑:现在是THREE.Raycaster (three.js r.56)

简短的答案是你必须考虑到canvas的offset

长的答案取决于你的代码是如何写的,所以我给你两个答案,这应该包括基础。

有很多可能的组合,所以你可能要试验。 另外,不同的浏览器可能会有所不同。

假设你的HTML是这样的:

 #canvas { width: 200px; height: 200px; margin: 100px; padding: 0px; position: static; /* fixed or static */ top: 100px; left: 100px; } <body> <div id="canvas"> </body> 

你的JS是这样的:

 var CANVAS_WIDTH = 200, CANVAS_HEIGHT = 200; var container = document.getElementById( 'canvas' ); document.body.appendChild( container ); renderer = new THREE.WebGLRenderer(); renderer.setSize( CANVAS_WIDTH, CANVAS_HEIGHT ); container.appendChild( renderer.domElement ); 

方法1为使以下方法正常工作,请将canvas位置设置为静态 ; 边距> 0,填充> 0即可

 mouse.x = ( ( event.clientX - renderer.domElement.offsetLeft ) / renderer.domElement.clientWidth ) * 2 - 1; mouse.y = - ( ( event.clientY - renderer.domElement.offsetTop ) / renderer.domElement.clientHeight ) * 2 + 1; 

方法2对于这种替代方法,设置canvas位置固定 ; 置顶> 0,置左> 0; 填充必须为0; 保证金> 0是好的

 mouse.x = ( ( event.clientX - container.offsetLeft ) / container.clientWidth ) * 2 - 1; mouse.y = - ( ( event.clientY - container.offsetTop ) / container.clientHeight ) * 2 + 1; 

这里是一个小提琴,如果你想实验: http : //jsfiddle.net/cn7ecoaa/

编辑:小提琴更新到three.js R.84

enent.clientX是客户端窗口偏移量,所以要计算鼠标位置,我们必须使用renderer元素客户端窗口偏移量。 使用element.getBoundingClientRect()获取元素矩形偏移窗口。

 var rect = renderer.domElement.getBoundingClientRect(); mouse.x = ( ( event.clientX - rect.left ) / ( rect.width - rect.left ) ) * 2 - 1; mouse.y = - ( ( event.clientY - rect.top ) / ( rect.bottom - rect.top) ) * 2 + 1; 
 <html> <head> <script src="build/three.min.js"></script> <link rel="stylesheet" href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" /> <style> body { font-family: Monospace; background-color: #fff; margin: 0px; overflow: hidden; } #canvas { background-color: #000; width: 200px; height: 200px; border: 1px solid black; margin: 10px; padding: 0px; top: 10px; left: 100px; } .border { padding:10px; margin:10px; } </style> </head> <body> <div class="border"> <div class="border"> <div id="canvas"></div> </div> </div> <script> // Three.js ray.intersects with offset canvas var container, camera, scene, renderer, mesh, objects = [], count = 0, CANVAS_WIDTH = 200, CANVAS_HEIGHT = 200; // info info = document.createElement( 'div' ); info.style.position = 'absolute'; info.style.top = '30px'; info.style.width = '100%'; info.style.textAlign = 'center'; info.style.color = '#f00'; info.style.backgroundColor = 'transparent'; info.style.zIndex = '1'; info.style.fontFamily = 'Monospace'; info.innerHTML = 'INTERSECT Count: ' + count; info.style.userSelect = "none"; info.style.webkitUserSelect = "none"; info.style.MozUserSelect = "none"; document.body.appendChild( info ); container = document.getElementById( 'canvas' ); renderer = new THREE.WebGLRenderer(); renderer.setSize( CANVAS_WIDTH, CANVAS_HEIGHT ); container.appendChild( renderer.domElement ); scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera( 45, CANVAS_WIDTH / CANVAS_HEIGHT, 1, 1000 ); camera.position.y = 250; camera.position.z = 500; camera.lookAt( scene.position ); scene.add( camera ); scene.add( new THREE.AmbientLight( 0x222222 ) ); var light = new THREE.PointLight( 0xffffff, 1 ); camera.add( light ); mesh = new THREE.Mesh( new THREE.BoxGeometry( 200, 200, 200, 1, 1, 1 ), new THREE.MeshPhongMaterial( { color : 0x0080ff } ) ); scene.add( mesh ); objects.push( mesh ); // find intersections var raycaster = new THREE.Raycaster(); var mouse = new THREE.Vector2(); // mouse listener document.addEventListener( 'mousedown', function( event ) { var rect = renderer.domElement.getBoundingClientRect(); mouse.x = ( ( event.clientX - rect.left ) / ( rect.width - rect.left ) ) * 2 - 1; mouse.y = - ( ( event.clientY - rect.top ) / ( rect.bottom - rect.top) ) * 2 + 1; raycaster.setFromCamera( mouse, camera ); intersects = raycaster.intersectObjects( objects ); if ( intersects.length > 0 ) { info.innerHTML = 'INTERSECT Count: ' + ++count; } }, false ); function render() { mesh.rotation.y += 0.01; renderer.render( scene, camera ); } (function animate() { requestAnimationFrame( animate ); render(); })(); </script> </body> </html> 

WestLangley,非常感谢你的解释。 像往常一样,这真的很有帮助。

就我而言,我把我的图表放在一个绝对定位的div中,所以我必须这样做:

  var offset = $('.rightBlock').offset(); mouse.x = ( ( event.clientX - offset.left ) / renderer.domElement.width ) * 2 - 1; mouse.y = - ( ( event.clientY - offset.top ) / renderer.domElement.height ) * 2 + 1; 

rightBlock是我的容器,只使用70%的屏幕。

你激励我,帮助我解决这个问题! 非常感谢。