javascript 在渲染器中捕捉特定网格上的点击事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12800150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
catch the click event on a specific mesh in the renderer
提问by Malloc
I set a canvas renderer which contain two meshs (cubes). What i need to do is to catch the click event on each cube
to call the convenient method for it.
我设置了一个包含两个网格(立方体)的画布渲染器。我需要做的是catch the click event on each cube
为它调用方便的方法。
So far, i could catch the click event on all the renderer, means when i click on cube1 and cube2, the click belong the same 'cause it's bound to the renderer
:)
到目前为止,我可以在所有渲染器上捕获单击事件,这意味着当我单击cube1 和cube2 时,单击属于相同的,因为它绑定到renderer
:)
My question is, how to bind the click event on each cube?
我的问题是,如何在每个立方体上绑定点击事件?
My relevant code is the following:
我的相关代码如下:
//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.
As you can see, cubeFor2D and cubeFor3D are contained in the renderer. I need to bind the click event on each mesh. I tried this with the threex.domevent.js
:
如您所见,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');
});
But it doesn't work, in the console, i got this error:
但它不起作用,在控制台中,我收到此错误:
TypeError: meshes.mesh1.on is not a function
Of course, i included the API source code file:
当然,我包含了 API 源代码文件:
<script src="threex.domevent.js"></script>
回答by WestLangley
You can generate a callback like this. First define your callback function for each object:
您可以生成这样的回调。首先为每个对象定义回调函数:
mesh.callback = function() { console.log( this.name ); }
Then follow the standard picking pattern:
然后遵循标准的拣货模式:
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();
}
}
EDIT: updated to three.js r.70
编辑:更新为three.js r.70
回答by Carlos Montiel
Create a click handler
window.addEventListener('click', onDocumentMouseDown, false);
Define the function onDocumentMouseDown, note that raycaster the difference in above answer is the index position of the object clicked!
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(); }}
Define the Mesh object
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);
define the callback function
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 ); }
创建点击处理程序
window.addEventListener('click', onDocumentMouseDown, false);
定义函数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(); }}
定义网格对象
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);
定义回调函数
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 ); }
So this code above will handle specific object clicked inside my canvas, then callback a function, the "mesh.callback" and it will remove some scene childs from the canvas.
所以上面的代码将处理在我的画布内单击的特定对象,然后回调一个函数,“mesh.callback”,它将从画布中删除一些场景子项。
It doesn't work if you use intersects[0].object.callback(); because at the index 0 the stored object are the vertices.
如果您使用 intersects[0].object.callback() 则不起作用;因为在索引 0 处,存储的对象是顶点。