Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 具有光线投射和相交测试的Three.js鼠标事件_Javascript_Three.js_Mouseevent_Raycasting - Fatal编程技术网

Javascript 具有光线投射和相交测试的Three.js鼠标事件

Javascript 具有光线投射和相交测试的Three.js鼠标事件,javascript,three.js,mouseevent,raycasting,Javascript,Three.js,Mouseevent,Raycasting,我是一个完整的Three.js新手,对javascript基本上是新手。我正在尝试测试一些鼠标事件交互。我尝试了很多方法,但都无法实现任何交互,所以我只是从下一页抓取了一些Javascript,将其调整为“MouseDown”,而不是“MouseOver”事件,并通常将其简化为没有旋转等:- 然而,结果页面有一个我不理解的问题。每当刷新页面时,多维数据集都会自动变为红色,但这只能在单击它时发生。如果我减小多维数据集的大小,那么这就解决了问题 我做了一个console.log(crossions

我是一个完整的Three.js新手,对javascript基本上是新手。我正在尝试测试一些鼠标事件交互。我尝试了很多方法,但都无法实现任何交互,所以我只是从下一页抓取了一些Javascript,将其调整为“MouseDown”,而不是“MouseOver”事件,并通常将其简化为没有旋转等:-

然而,结果页面有一个我不理解的问题。每当刷新页面时,多维数据集都会自动变为红色,但这只能在单击它时发生。如果我减小多维数据集的大小,那么这就解决了问题

我做了一个
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;
}