【问题标题】:catch the click event on a specific mesh in the renderer在渲染器中捕获特定网格上的点击事件
【发布时间】:2012-09-29 18:59:33
【问题描述】:

我设置了一个包含两个网格(立方体)的画布渲染器。我需要做的是 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>

【问题讨论】:

标签: javascript three.js


【解决方案1】:

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

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

【讨论】:

  • 有什么方法可以检测立方体的哪一侧被点击以及点击那一侧的 x,y 是多少?
  • 如有问题请发新帖。
  • 我有一扇门,它有几个元素,如铰链、螺丝、锚、枢轴等。所以点击我没有得到准确的,可能是因为它们重叠。有什么办法可以解决这个问题?任何帮助将不胜感激。
  • @user2906608 有问题需要发新帖。
  • 注意-如果三个画布没有覆盖整个屏幕,请将鼠标事件设置在renderer.domElement上并使用event.offsetXevent.offsetY
【解决方案2】:
  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 处存储的对象是顶点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多