Threejs是一个非常棒的图形库,可是对于一些交互逻辑,实现起来就没有那么容易了,这篇我们来讲解下如何实现一些常见的交互操作,比如点击、mouseover等效果。
首先来看看Threejs是如何实现交互的。在3d的世界中,我们选取一个物体不像2d平面立面那么简单,因为我们所对应的是一个3维的世界,而鼠标所在的屏幕是一个2d的世界。这个时候Threejs会为我们提供一个叫做Raycaster的类,为我们提供的是一个射线,然后我们可以根据不同的方向去发射射线,根据射线是否被阻挡,来判断我们是否碰到了物体。
我们来看看如何使用Raycaster类来实现鼠标滑过物体的显示效果,首先我们实例化raycaseer的对象,以及一个记录鼠标位置的坐标mouse,选中的3d模型selectedObject ,选中的3d模型材质selectedMaterial,高亮的材质hightLightMaterial。
var raycaster = new THREE.Raycaster(); var mouse = new THREE.Vector2(); var selectedObject = null; var selectedMaterial = null; var hightLightMaterial = new THREE.MeshBasicMaterial({ color: 'green' });
然后我们在主循环中实现raycaster的射线测试工作
function render() { requestAnimationFrame(render); //设置射线从摄像机视角开始,沿着坐标射出 raycaster.setFromCamera(mouse, camera); //获取射线击中的Objects var intersects = raycaster.intersectObjects(cubes, true); if (intersects.length > 0) { var obj = intersects[0].object; if (selectedObject != obj) { //设置选中效果 setSelectedStatus(obj); } } else { //no object intersected 恢复原先的显示 restoreObjectStatus(); } renderer.render(scene, camera); }; <span class="redactor-invisible-space"> function setSelectedStatus(obj) { if (selectedObject) restoreObjectStatus(); selectedObject = obj; selectedMaterial = obj.material; selectedObject.material = hightLightMaterial; } function restoreObjectStatus() { if (selectedObject) selectedObject.material = selectedMaterial; selectedObject = null; selectedMaterial = null; } <span class="redactor-invisible-space"> </span></span>
实现了mouseover以后,点击事件就显得比较简单了,我们只需要在注册mousedown事件,然后判断是否有选中object
document.addEventListener('mousedown', onDocumentMouseDown, false); <span class="redactor-invisible-space">function onDocumentMouseDown(event) { boxHelper.update(selectedObject); boxHelper.visible = true; }</span>
boxhelper是一个显示object外框的辅助类,我们用来显示选中效果,初始化代码如下
var boxHelper = new THREE.BoxHelper(camera, 0xff0000); boxHelper.visible = false; scene.add(boxHelper);
最终效果如下: