12

我设置了一个包含两个网格(立方体)的画布渲染器。我需要做的是catch the click event on each cube为它调用方便的方法。

到目前为止,我可以在所有渲染器上捕获点击事件,这意味着当我点击 cube1 和 cube2 时,点击属于相同的,因为它绑定到renderer:)

我的问题是,如何在每个立方体上绑定点击事件?

我的相关代码如下:

            //dom
    var containerPopUp=document.getElementById('popup');
    //renderer
    var rendererPopUp = new THREE.CanvasRenderer();
    rendererPopUp.setSize(420,200);

    containerPopUp.appendChild(rendererPopUp.domElement);
    //Scene
    var scenePopUp = new THREE.Scene();
    //Camera
    var cameraPopUp = new THREE.PerspectiveCamera(50,60/60,1,1000);

    cameraPopUp.position.z = 220;
    cameraPopUp.position.y =  20;
    //
    scenePopUp.add(cameraPopUp);

    //Add texture for the cube
    //Use image as texture
    var img2D = new THREE.MeshBasicMaterial({ //CHANGED to MeshBasicMaterial
    map:THREE.ImageUtils.loadTexture('img/2d.png') 
    });
    img2D.map.needsUpdate = true; //ADDED
    //Add Cube
    var cubeFor2D = new THREE.Mesh(new THREE.CubeGeometry(40,80,40),img2D);
    cubeFor2D.position.x =- 60;
    cubeFor2D.position.y = 20;

    scenePopUp.add(cubeFor2D);
    //
    var img3D = new THREE.MeshBasicMaterial({ //CHANGED to MeshBasicMaterial
    map:THREE.ImageUtils.loadTexture('img/3d.png') 
    });
    img3D.map.needsUpdate = true;
    var cubeFor3D = new THREE.Mesh(new THREE.CubeGeometry(40,80,40),img3D);
    cubeFor3D.position.x = 60;
    cubeFor3D.position.y=20;

    scenePopUp.add(cubeFor3D);
    //
    rendererPopUp.render(scenePopUp,cameraPopUp);
    //
    animate();

    rendererPopUp.domElement.addEventListener('click',testCall,false);//Here the click event is bound on the whole renderer, means what ever object in the renderer is clicked, the testCall method is called.

如您所见,cubeFor2D 和 cubeFor3D 包含在渲染器中。我需要在每个网格上绑定点击事件。我试过这个threex.domevent.js

var meshes  = {};
        meshes['mesh1'] = cubeFor2D;
        meshes['mesh1'].on('mouseover', function(event){

              //response to click...
              console.log('you have clicked on cube 2D');

        });

但它不起作用,在控制台中,我收到了这个错误:

TypeError: meshes.mesh1.on is not a function

当然,我包含了 API 源代码文件:

    <script src="threex.domevent.js"></script>
4

2 回答 2

32

您可以像这样生成回调。首先为每个对象定义你的回调函数:

mesh.callback = function() { console.log( this.name ); }

然后遵循标准的拣货模式:

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

function onDocumentMouseDown( event ) {

    event.preventDefault();

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

    raycaster.setFromCamera( mouse, camera );

    var intersects = raycaster.intersectObjects( objects ); 

    if ( intersects.length > 0 ) {

        intersects[0].object.callback();

    }

}

编辑:更新到three.js r.70

于 2012-10-09T21:53:57.593 回答
0
  1. 创建点击处理程序

    window.addEventListener('click', onDocumentMouseDown, false);
    
  2. 定义onDocumentMouseDown函数,注意上面答案中raycaster的区别是点击对象的索引位置!

    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();
    function onDocumentMouseDown( event ) {
    event.preventDefault();
    mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
    raycaster.setFromCamera( mouse, camera );
    console.log(scene.children);
    var intersects = raycaster.intersectObjects( scene.children );
    console.log(intersects[1]);
    if ( intersects.length > 0 ) {
        intersects[1].object.callback();
    }}
    
  3. 定义网格对象

    var mesh_menu_title = new THREE.Mesh(geometry_menu, materials_menu);
    mesh_menu_title.name = 'select_lang';
    mesh_menu_title.callback = function() { select_language();}
    scene.add(mesh_menu_title);
    
  4. 定义回调函数

    function select_language(){
    var selectedObject = scene.getObjectByName("select_lang"); 
    scene.remove( selectedObject );
    var selectedObject = scene.getObjectByName("start");
    scene.remove( selectedObject );
    var selectedObject = scene.getObjectByName("menu");
    scene.remove( selectedObject );
    }
    

因此,上面的代码将处理在我的画布中单击的特定对象,然后回调一个函数,“mesh.callback”,它将从画布中删除一些场景子对象。

如果您使用 intersects[0].object.callback(); 则不起作用 因为在索引 0 处,存储的对象是顶点。

于 2019-04-15T16:58:48.600 回答