一、在threejs中添加点击事件的必要性
在threejs渲染的3D场景中,我们往往需要让用户对模型进行交互,例如在一个3D房间场景中,用户需要通过点击鼠标来打开门或者窗户等。如果加入交互功能,用户体验会更加丰富,而不是仅仅作为一个静态的3D渲染模型。因此,在threejs中实现模型点击事件是一个必要且重要的功能。
二、实现模型交互的基本方法
首先我们需要在threejs场景中找到对应的模型,然后将点击事件绑定到该模型上,随后通过点击事件处理函数实现模型的交互。
三、确定模型
在threejs中处理模型交互之前,我们需要知道当前场景中的模型是哪一个。在确定模型过程中,可以使用Raycaster对象。
// 初始化射线辅助器 var raycaster = new THREE.Raycaster(); // 鼠标控制对象 var mouse = new THREE.Vector2(); // 监听鼠标的移动事件 document.addEventListener('mousemove', onDocumentMouseMove, false); // 鼠标移动事件处理函数 function onDocumentMouseMove(event){ // 得到鼠标相对于容器的坐标 mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = - (event.clientY / window.innerHeight) * 2 + 1; }
四、绑定点击事件
在确定了当前场景中的模型之后,我们需要将点击事件绑定到该模型上。
// 绑定点击事件 document.addEventListener('click', onDocumentClick, false); // 点击事件处理函数 function onDocumentClick(event) { // 执行射线检测 raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObjects(objects, true); // 判断是否成功 if (intersects.length > 0) { // 选取第一个物体并对其执行交互 var object = intersects[0].object; interactWithObject(object); } }
五、执行交互
在确定了需要交互的对象后,我们需要执行对应的交互操作。
// 交互函数 function interactWithObject(object){ // 判断是否是需要进行交互的模型 if(object.name == "door"){ // 打开门的动画 }else if(object.name == "window"){ // 打开窗户的动画 }else{ // do nothing } }
六、完整的示例代码
// 场景 var scene = new THREE.Scene(); // 摄像机 var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 添加模型 var boxGeometry = new THREE.BoxGeometry(1, 1, 1); var boxMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); var box = new THREE.Mesh(boxGeometry, boxMaterial); box.position.set(0, 0, -5); box.name = "box"; scene.add(box); // 初始化射线辅助器 var raycaster = new THREE.Raycaster(); // 鼠标控制对象 var mouse = new THREE.Vector2(); // 监听鼠标的移动事件 document.addEventListener('mousemove', onDocumentMouseMove, false); // 鼠标移动事件处理函数 function onDocumentMouseMove(event) { // 得到鼠标相对于容器的坐标 mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = - (event.clientY / window.innerHeight) * 2 + 1; } // 绑定点击事件 document.addEventListener('click', onDocumentClick, false); // 点击事件处理函数 function onDocumentClick(event) { // 执行射线检测 raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObjects(scene.children, true); // 判断是否成功 if (intersects.length > 0) { // 选取第一个物体并对其执行交互 var object = intersects[0].object; interactWithObject(object); } } // 交互函数 function interactWithObject(object) { // 判断是否是需要进行交互的模型 if (object.name == "box") { // 给box添加动画 var tween = new TWEEN.Tween(object.rotation) .to({ x:Math.PI*2, y:Math.PI*2 }, 1000) .start(); } else { // do nothing } } // 持续渲染 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();