使用 THREE.Raycaster - 我总是得到 id 8?

Using THREE.Raycaster - I get always the id 8?

我想创建一个显示一定数量 "THREE.Meshes" 的仪表板。当我用鼠标点击其中一个时,我想调用一个函数来识别我点击的内容。

我的问题: 我总是从 "callFromTitleWithId" 函数中得到 ID:8 。我用鼠标点击选择了哪一个都没有关系。

也许有人可以帮忙,我找不到错误:(

这是完整的示例:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>TEST</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        <style>
            body { margin: 0;
            background: black; }
            canvas { width: 100%; height: 100% }
        </style>
    </head>

    <body>
        <!-- Bibs -->
        <script src="../extlib/webthree/build/three.js"></script>
        <script>
            document.addEventListener('mousedown', onDocumentMouseDown, false);

            var arrayTiles = [];

            //[SCREEN]
            var SCREEN_WIDTH = window.innerWidth - 5;
            var SCREEN_HEIGHT = window.innerHeight - 5;

            screenOrientationValue=0;

            //RayCaster für Objekte
            var raycaster2 = new THREE.Raycaster(new THREE.Vector3(0,0,35),new THREE.Vector3(0,0,1));
            var mouse2 = new THREE.Vector2();

            var renderer = new THREE.WebGLRenderer();
            renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
            document.body.appendChild( renderer.domElement );

            var sceneWorld = new THREE.Scene();
            sceneWorld.add( new THREE.AxesHelper(50) );
            createTiles(sceneWorld);

            var camera= new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
            camera.position.set(0,0,35);

            var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
            light2.position.set( 30, -10, 30 );
            sceneWorld.add( light2 );


            var animate = function () {

                requestAnimationFrame( animate );
                renderer.render( sceneWorld, camera);
                sceneUpdate();
            };

            animate();

            function sceneUpdate()
            {
                //Update            
            }

            function callFromTitleWithId(titleId)
            {
                console.log("ID:"+titleId);
            }

            function onDocumentMouseDown(event)
            {
                event.preventDefault();



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

                    raycaster2.setFromCamera(mouse2, camera);

                    var intersects2 = raycaster2.intersectObjects(arrayTiles,true);

                    if (intersects2.length > 0) {
                          console.log('Maus: X:'+mouse2.x+' Y:'+mouse2.y);
                          console.log("intersects:" + intersects2[0].object);
                          console.log("distance:" + intersects2[0].distance);
                          console.log("face:" + intersects2[0].face);
                          console.log("faceIndex:" + intersects2[0].faceIndex);
                          console.log("faceIndex y:" + intersects2[0].point.y);
                          console.log("faceIndex x:" + intersects2[0].point.x);

                          intersects2[0].object.callback();                       
                    }
            }

            function createTiles(sceneWorld)
            {
                var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
                var materialSide = new THREE.MeshBasicMaterial( {color: 0xffff00} );
                var materialsTiles = [materialSide, // Left side
                materialSide, // Right side
                materialSide, // Top side   ---> THIS IS THE FRONT
                materialSide, // Bottom side --> THIS IS THE BACK
                material, // Front side
                materialSide  // Back side
                ];

                var maxTileSizeWidth=11;
                var maxTileSizeHeight=8;

                var distanceBetween=2;
                var distanceBorderLeft=-1;

                var countInColumns=2;
                var countInRow = 4;

                var startCoordinatesX = ((((countInColumns * maxTileSizeWidth)+(countInColumns-6.5)*distanceBetween)/2))*-1;
                var startCoordinatesY = 20;

                var actualCoordinatesX = startCoordinatesX;
                var actualCoordinatesY = startCoordinatesY;

                //id for test
                var idNumberForTest=0;

                let r;
                for(r=1; r<=countInRow; r++ )
                {
                    let i;
                    for(i=1; i<=countInColumns; i++ )
                    {
                        var geometry = new THREE.BoxGeometry(maxTileSizeWidth, maxTileSizeHeight, 1 );
                        var tileX = new THREE.Mesh( geometry, materialsTiles );
                        tileX.position.set(actualCoordinatesX,actualCoordinatesY,0);

                        //Change actualCoordinates X
                        actualCoordinatesX = actualCoordinatesX + maxTileSizeWidth + distanceBetween;

                        idNumberForTest=idNumberForTest + 1;
                        tileX.callback = function(){callFromTitleWithId(idNumberForTest+'')};
                        arrayTiles.push(tileX);

                        sceneWorld.add( tileX );
                    }

                    actualCoordinatesY = actualCoordinatesY - (maxTileSizeHeight+1);
                    actualCoordinatesX = startCoordinatesX;
                }
            }
        </script>
    </body>
</html>

`

问题是 idNumberForTest 对所有对象都是相等的。回调函数总是引用同一个变量。除了使用回调函数,您还可以像这样存储单击的网格的 ID:

tileX.userData.id = idNumberForTest;

这样,正确的ID就分配给了相应的对象。查看以下实时示例,了解这种方法的实际应用。

document.addEventListener('mousedown', onDocumentMouseDown, false);

var arrayTiles = [];

//[SCREEN]
var SCREEN_WIDTH = window.innerWidth - 5;
var SCREEN_HEIGHT = window.innerHeight - 5;

screenOrientationValue=0;

//RayCaster für Objekte
var raycaster2 = new THREE.Raycaster(new THREE.Vector3(0,0,35),new THREE.Vector3(0,0,1));
var mouse2 = new THREE.Vector2();

var renderer = new THREE.WebGLRenderer();
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
document.body.appendChild( renderer.domElement );

var sceneWorld = new THREE.Scene();
sceneWorld.add( new THREE.AxesHelper(50) );
createTiles(sceneWorld);

var camera= new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,35);

var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
light2.position.set( 30, -10, 30 );
sceneWorld.add( light2 );


var animate = function () {

 requestAnimationFrame( animate );
 renderer.render( sceneWorld, camera);
 sceneUpdate();
};

animate();

function sceneUpdate()
{
 //Update            
}

function callFromTitleWithId(titleId)
{
 console.log("ID:"+titleId);
}

function onDocumentMouseDown(event)
{
 event.preventDefault();

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

 raycaster2.setFromCamera(mouse2, camera);
 
 console.log( arrayTiles );

 var intersects2 = raycaster2.intersectObjects(arrayTiles,true);

 if (intersects2.length > 0) {
  console.log('Maus: X:'+mouse2.x+' Y:'+mouse2.y);
  console.log("intersects:" + intersects2[0].object);
  console.log("distance:" + intersects2[0].distance);
  console.log("face:" + intersects2[0].face);
  console.log("faceIndex:" + intersects2[0].faceIndex);
  console.log("faceIndex y:" + intersects2[0].point.y);
  console.log("faceIndex x:" + intersects2[0].point.x);

  console.log("ID:", intersects2[0].object.userData.id);                
 }
}

function createTiles(sceneWorld)
{
 var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
 var materialSide = new THREE.MeshBasicMaterial( {color: 0xffff00} );
 var materialsTiles = [materialSide, // Left side
            materialSide, // Right side
            materialSide, // Top side   ---> THIS IS THE FRONT
            materialSide, // Bottom side --> THIS IS THE BACK
            material, // Front side
            materialSide  // Back side
            ];

 var maxTileSizeWidth=11;
 var maxTileSizeHeight=8;

 var distanceBetween=2;
 var distanceBorderLeft=-1;

 var countInColumns=2;
 var countInRow = 4;

 var startCoordinatesX = ((((countInColumns * maxTileSizeWidth)+(countInColumns-6.5)*distanceBetween)/2))*-1;
 var startCoordinatesY = 20;

 var actualCoordinatesX = startCoordinatesX;
 var actualCoordinatesY = startCoordinatesY;

 //id for test
 var idNumberForTest=0;

 let r;
 for(r=1; r<=countInRow; r++ )
 {
  let i;
  for(i=1; i<=countInColumns; i++ )
  {
   var geometry = new THREE.BoxGeometry(maxTileSizeWidth, maxTileSizeHeight, 1 );
   var tileX = new THREE.Mesh( geometry, materialsTiles );
   tileX.position.set(actualCoordinatesX,actualCoordinatesY,0);

   //Change actualCoordinates X
   actualCoordinatesX = actualCoordinatesX + maxTileSizeWidth + distanceBetween;

   idNumberForTest=idNumberForTest + 1;
   arrayTiles.push(tileX);
   tileX.userData.id = idNumberForTest;

   sceneWorld.add( tileX );
  }

  actualCoordinatesY = actualCoordinatesY - (maxTileSizeHeight+1);
  actualCoordinatesX = startCoordinatesX;
 }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>