Javascript 具有光线投射和相交测试的Three.js鼠标事件
我是一个完整的Three.js新手,对javascript基本上是新手。我正在尝试测试一些鼠标事件交互。我尝试了很多方法,但都无法实现任何交互,所以我只是从下一页抓取了一些Javascript,将其调整为“MouseDown”,而不是“MouseOver”事件,并通常将其简化为没有旋转等:- 然而,结果页面有一个我不理解的问题。每当刷新页面时,多维数据集都会自动变为红色,但这只能在单击它时发生。如果我减小多维数据集的大小,那么这就解决了问题 我做了一个Javascript 具有光线投射和相交测试的Three.js鼠标事件,javascript,three.js,mouseevent,raycasting,Javascript,Three.js,Mouseevent,Raycasting,我是一个完整的Three.js新手,对javascript基本上是新手。我正在尝试测试一些鼠标事件交互。我尝试了很多方法,但都无法实现任何交互,所以我只是从下一页抓取了一些Javascript,将其调整为“MouseDown”,而不是“MouseOver”事件,并通常将其简化为没有旋转等:- 然而,结果页面有一个我不理解的问题。每当刷新页面时,多维数据集都会自动变为红色,但这只能在单击它时发生。如果我减小多维数据集的大小,那么这就解决了问题 我做了一个console.log(crossions
console.log(crossions)
,发现刷新时的值是“5”,但此后每次单击多维数据集时,值都是“1”。我希望刷新时的值为“0”,因为我还没有实际单击任何内容?知道了这一点,我可以很容易地添加一个额外的“如果”语句,如下所示:
if (intersects.length > 4)
{
INTERSECTED.material.emissive.setHex( 0x111111 );
}
这在某种程度上解决了这个问题,但我仍然想知道为什么这个问题首先会发生
如何进一步简化此代码,以便获得一个基本模板,从中可以创建未来的鼠标单击事件类型页面?例如,如果我希望立方体在单击时旋转,那么现在似乎不起作用
代码如下:
<script src="js/three.js"></script>
<script>
var camera, scene, raycaster, renderer;
var mouse = new THREE.Vector2(), INTERSECTED;
var radius = 100;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
scene = new THREE.Scene();
scene.add( new THREE.AmbientLight( 0xffffff, 0.2 ) );
var light = new THREE.DirectionalLight( 0xffffff, 2 );
light.position.set( 30, 10, 1 ).normalize();
scene.add( light );
var cubeGeometry = new THREE.BoxGeometry(20,20,20);
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x999999, wireframe: false});
var object = new THREE.Mesh(cubeGeometry, cubeMaterial);
object.position.x = 0;
object.position.y = 0;
object.position.z = 0;
scene.add( object );
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function animate() {
requestAnimationFrame( animate );
render();
}
camera.position.x = -30;
camera.position.y = 30;
camera.position.z = 30;
camera.lookAt( scene.position );
camera.updateMatrixWorld();
function render()
{
// find intersections
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( scene.children );
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].object ) {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = intersects[ 0 ].object;
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
INTERSECTED.material.emissive.setHex( 0xff0000 );
console.log(intersects.length);
}
} else {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = null;
}
renderer.render( scene, camera );
}
</script>
var摄影机、场景、光线投射器、渲染器;
var mouse=new THREE.Vector2(),相交;
var半径=100;
init();
制作动画();
函数init(){
container=document.createElement('div');
文件.正文.附件(容器);
var info=document.createElement('div');
info.style.position='绝对';
info.style.top='10px';
info.style.width='100%';
info.style.textAlign='center';
摄像头=新的三个透视摄像头(70,window.innerWidth/window.innerHeight,11000);
场景=新的三个。场景();
添加(新的三个环境光(0xffffff,0.2));
var灯=新的三方向灯(0xffffff,2);
light.position.set(30,10,1).normalize();
场景。添加(灯光);
var立方几何=新的三箱几何(20,20,20);
var cubeMaterial=new THREE.MeshLambertMaterial({颜色:0x999999,线框:false});
var对象=新的三网格(立方几何、立方材质);
object.position.x=0;
object.position.y=0;
object.position.z=0;
场景。添加(对象);
raycaster=new-THREE.raycaster();
renderer=new THREE.WebGLRenderer();
renderer.setClearColor(0xF0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth、window.innerHeight);
renderer.sortObjects=false;
container.appendChild(renderer.domeElement);
文件。添加的文件列表('mousedown',onDocumentMouseDown,false);
addEventListener('resize',onWindowResize,false);
}
函数onWindowResize(){
camera.aspect=window.innerWidth/window.innerHeight;
camera.updateProjectMatrix();
renderer.setSize(window.innerWidth、window.innerHeight);
}
函数onDocumentMouseDown(事件){
event.preventDefault();
mouse.x=(event.clientX/window.innerWidth)*2-1;
mouse.y=-(event.clientY/window.innerHeight)*2+1;
}
函数animate(){
请求动画帧(动画);
render();
}
camera.position.x=-30;
摄像机位置y=30;
摄像机位置z=30;
摄像机。注视(场景。位置);
camera.updateMatrix世界();
函数render()
{
//寻找交叉点
raycaster.setFromCamera(鼠标、相机);
var intersects=raycaster.intersectObjects(scene.children);
如果(相交长度>0){
if(相交!=相交[0]。对象){
如果(相交)相交.material.emissive.setHex(相交.currentHex);
相交=相交[0]。对象;
INTERSECTED.currentHex=INTERSECTED.material.emissive.getHex();
交叉。材料。发射。setHex(0xff0000);
控制台.日志(交叉.长度);
}
}否则{
如果(相交)相交.material.emissive.setHex(相交.currentHex);
相交=空;
}
渲染器。渲染(场景、摄影机);
}
当您声明var mouse=new THREE.Vector2()
时,这意味着您创建了一个值为{x:0,y:0}
的向量(这意味着您的鼠标位于屏幕中央)。然后使用init()
初始化场景,在那里设置立方体,然后使用animate()
开始渲染
现在,将鼠标放在屏幕的中心,并在每次渲染(在render()
函数中)上检查交点。这意味着,当你在屏幕中间的<代码>鼠标<代码>时,你会得到交叉的肯定结果。当你点击立方体外的某个地方时,你设置了一个新的鼠标点,所以相交结果是负数
由于要与鼠标单击交互,最好将检查交叉点的代码块从render()
移动到onDocumentMouseDown(事件)
因此,只有在单击场景时才能检查交叉点
示例您好,谢谢!这很有帮助。只是想知道我会如何做一个布尔点击交互:如果立方体是灰色的,点击就会变成红色;如果它是红色的,那么单击一下就会将其变回灰色?@user62109您可以检查与光线相交的对象的颜色。访问并将其设置为:
INTERSECTED.material.color.setHex(0xff0000)
。
// find intersections
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( scene.children );
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].object ) {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = intersects[ 0 ].object;
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
INTERSECTED.material.emissive.setHex( 0xff0000 );
console.log(intersects.length);
}
} else {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = null;
}