以上一篇入门篇为例来简单的设置下3d模型当中的交互事件,上一篇我们已经完成了在3d页面中添加了一个红色球,下面我们给这个球一个点击事件让它Y轴位置上升,再设置一个鼠标移入到球上时让其变色。

1.其实three.js当中没有事件可以直接选中物体的,我们需要监听window对象来完成与3d页面的交互,通过使用到three.js当中RayCaster对象,用于在三维空间中进行鼠标拾取,原理是:相机与鼠标所在的设备坐标之间的连线与哪些物体相交。相交的物体离屏幕越近的越靠前,所以第一个物体就是我们选中的对象。

第一步:给window对象添加点击事件监听器;

  1. window.addEventListener('mousedown', mouseDownFuc);

第二步:在事件监听函数里拾取到点击的对象集合;

  1. function mouseDownFuc(){
  2. let raycaster = new THREE.Raycaster();//创建光线投射对象
  3. let mouse = new THREE.Vector2();//创建二维平面
  4. let intersectsObjArr = getSelsectOBj(mouse,raycaster, e);//通过封装的getSelsectOBj函数获取鼠标选中对象集合,e是点击事件对象
  5. }
  6. //获取事件操作对象
  7. function getSelsectOBj(mouse,raycaster, e) {
  8. //将html坐标系转化为webgl坐标系,并确定鼠标点击位置
  9. mouse.x = e.clientX / renderer.domElement.clientWidth*2-1;
  10. mouse.y = -(e.clientY / renderer.domElement.clientHeight*2)+1;
  11. raycaster.setFromCamera(mouse,camera);//以camera为z坐标,确定所点击物体的3D空间位置
  12. let intersects = raycaster.intersectObjects(scene.children, true);//确定所点击位置上的物体数量集合
  13. return intersects;//返回连线经过的物体集合
  14. }

第三步:判断intersectsObjArr集合长度不为零,确认我们鼠标点击的地方有物体,如果有物体那么intersectsObjArr[0]就是我们选中的对象,通过页面console.log(intersectsObjArr[0])发现intersectsObjArr[0]包含了相交点的许多信息,而我们只需要交点的对象,所以我们需要取到intersectsObjArr[0].object对象;然后我们还需要进行一次判断当前对象就是我们点击的对象,在这里我们还得回到创建物体时给它的name属性一个值进行区分物体。最后给它position属性值的Y轴坐标设为50;

  1. myBall.name = 'redBall';//创建物体时给它name属性一个名称
  2. if(intersectsObjArr.length > 0){
  3. if(intersectsObjArr[0].object.name == 'redBall'){
  4. intersectsObjArr[0].object.position.y = 50;
  5. }
  6. }

以上就是我们完成了3d页面物体点击事件,然后就是鼠标的移入到物体变色,移出时颜色还原,这和2d页面的移入移出不太一样,因为我们是给window对象加的监听器,然后通过RayCaster对象来拾取到物体的,所以我们这里需要给window对象加鼠标移动事件来判断鼠标是否移动我们的物体上。其步骤同上点击事件一样。

  1. window.addEventListener('mousemove', mouseMoveFuc);
  2. function mouseMoveFuc(){
  3. let raycaster = new THREE.Raycaster();//创建光线投射对象
  4. let mouse = new THREE.Vector2();//创建二维平面
  5. let intersectsObjArr = getSelsectOBj(mouse,raycaster, e);//通过封装的getSelsectOBj函数获取鼠标选中对象集合,e是点击事件对象
  6. if(intersectsObjArr.length > 0){
  7. if(intersectsObjArr[0].object.name == 'redBall'){
  8. intersectsObjArr[0].object.material = new THREE.MeshPhongMaterial( { color: 'orange'});//移到物体上时颜色变成橘色
  9. document.getElementsByTagName('body')[0].style.cursor = 'pointer';//移到物体上时鼠标显示为手
  10. }
  11. }else{
  12. myBall.material = new THREE.MeshPhongMaterial( { color: 0xff0000});//移出物体时颜色变成原来的红色
  13. document.getElementsByTagName('body')[0].style.cursor = 'default';//移出物体时鼠标显示为默认
  14. }
  15. }

贴上最终代码:运行一下,看下效果

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset=utf-8>
  5. <title>event</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. padding: 0;
  10. height: 100vh;
  11. width: 100vw;
  12. overflow: hidden;
  13. background: url('img/bgImg.jpg') no-repeat fixed;
  14. background-size: 100% 100%;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <script src="lib/three.min.js"></script>
  20. <script src="lib/OrbitControls.js"></script>
  21. <script>
  22. window.onload = function(){
  23. let scene,camera,renderer,myBall;
  24. initThreeScene();
  25. //物体的事件交互
  26. window.addEventListener('mousedown', mouseDownFuc);
  27. window.addEventListener('mousemove', mouseMoveFuc);
  28. function mouseDownFuc (e) {
  29. let raycaster = new THREE.Raycaster();//光线投射,用于确定鼠标点击位置
  30. let mouse = new THREE.Vector2();//创建二维平面
  31. let intersects = getSelsectOBj(mouse,raycaster, e);
  32. if(intersects.length > 0) {
  33. console.log(intersects[0])
  34. if(intersects[0].object.name == 'myBall') {
  35. myBall.position.y = 50;
  36. }
  37. }
  38. }
  39. function mouseMoveFuc (e) {
  40. let raycaster = new THREE.Raycaster();//光线投射,用于确定鼠标点击位置
  41. let mouse = new THREE.Vector2();//创建二维平面
  42. let intersects = getSelsectOBj(mouse,raycaster, e);
  43. if(intersects.length > 0) {
  44. if(intersects[0].object.name == 'myBall') {
  45. myBall.material = new THREE.MeshPhongMaterial( { color: 'orange'});
  46. document.getElementsByTagName('body')[0].style.cursor = 'pointer';
  47. }
  48. }else {
  49. myBall.material = new THREE.MeshPhongMaterial( { color: 0xff0000});
  50. document.getElementsByTagName('body')[0].style.cursor = 'default';
  51. }
  52. }
  53. //获取事件操作对象
  54. function getSelsectOBj(mouse,raycaster, e) {
  55. //将html坐标系转化为webgl坐标系,并确定鼠标点击位置
  56. mouse.x = e.clientX / renderer.domElement.clientWidth*2-1;
  57. mouse.y = -(e.clientY / renderer.domElement.clientHeight*2)+1;
  58. //以camera为z坐标,确定所点击物体的3D空间位置
  59. raycaster.setFromCamera(mouse,camera);
  60. //确定所点击位置上的物体数量
  61. let intersects = raycaster.intersectObjects(scene.children, true);
  62. return intersects;
  63. }
  64. function initThreeScene() {
  65. scene = new THREE.Scene();
  66. camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 2000 );
  67. camera.position.set( 0, 50,300 );   
  68. renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });//antialias: true;让渲染的平面是光滑的,alpha: true;让渲染的3d背景透明。
  69. renderer.setSize( window.innerWidth, window.innerHeight );
  70. document.body.appendChild(renderer.domElement );
  71. // 给场景添加一个环境光
  72.     let ambientLight = new THREE.AmbientLight( 0xf5f5f5);
  73. scene.add( ambientLight );
  74. //辅助线
  75. let grid = new THREE.GridHelper( 400, 30, 0xcccccc, 0xcccccc );
  76. scene.add( grid );
  77. //创建的球
  78. let ball = new THREE.SphereGeometry( 25, 100, 100 );//25:球半径 第一个100:水平分割面的数量. 第二个100:垂直分割面的数量.
  79. let ballColor = new THREE.MeshPhongMaterial( { color: 0xff0000 } );
  80. myBall = new THREE.Mesh( ball , ballColor );
  81. myBall.name = 'myBall';
  82. scene.add( myBall );
  83. let controls =new THREE.OrbitControls(camera, renderer.domElement);
  84. controls.enableZoom =true;//允许缩放
  85. //设置相机移动距离
  86. controls.minDistance = 1;
  87. controls.maxDistance = 2000;
  88. controls.enableRotate =true;
  89. function render() {
  90. requestAnimationFrame( render );
  91. renderer.render( scene, camera );
  92. }
  93. render();
  94. window.onresize = function () {
  95.     camera.aspect = window.innerWidth / window.innerHeight;//相机重置可视范围
  96.     camera.updateProjectionMatrix();
  97.     renderer.setSize( window.innerWidth, window.innerHeight );//渲染器重新渲染可视范围
  98. }
  99. }
  100. }
  101. </script>
  102. </body>
  103. </html>

three.js中的事件的更多相关文章

  1. 怎么理解js中的事件委托

    怎么理解js中的事件委托 时间 2015-01-15 00:59:59  SegmentFault 原文  http://segmentfault.com/blog/sunchengli/119000 ...

  2. js中冒泡事件和捕获事件

    js中冒泡事件和捕获事件: 冒泡事件:冒泡事件是从里向外,即是从被绑定元素开始一直向外到达页面的所有祖先元素都会被触发,这 一过程被称为事件冒泡.这个事件从原始元素开始一直冒泡到DOM树的最上层 捕获 ...

  3. 看懂此文,不再困惑于 JS 中的事件设计

    看懂此文,不再困惑于 JS 中的事件设计 今天刚在关注的微信公众号看到的文章,关于JS事件的,写的很详细也很容易理解,相关的知识点都有总结到,看完就有种很舒畅的感觉,该串起来的知识点都串起来了.反正一 ...

  4. js中冒泡事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. DOM 以及JS中的事件

    [DOM树节点] DOM节点分为三大节点:元素节点,文本节点,属性节点. 文本节点,属性节点为元素节点的两个子节点通过getElment系列方法,可以去到元素节点 [查看节点] 1 document. ...

  6. 从零开始的JS生活(二)——BOM、DOM与JS中的事件

    上回书说道,JS中变量.运算符.分支结构.循环和嵌套循环等内容.本回就由本K给大伙唠唠JS中的BOM.DOM和事件. 一."花心大萝卜"--BOM 1.震惊,FFF团为何对BOM举 ...

  7. js中的事件,内置对象,正则表达式

    [JS中的事件分类] 1.鼠标事件: click/dbclick/mouseover/mouseout/mousemove/mousedown/mouseup 2.键盘事件: keydown: 键盘按 ...

  8. JS中的事件以及DOM 操作

    [DOM树节点] DOM节点分为三大节点:元素节点,文本节点,属性节点. 文本节点,属性节点为元素节点的两个子节点通过getElment系列方法,可以去到元素节点 [查看节点] 1 document. ...

  9. JS中的事件&对象

    一.JS中的事件 (一)JS中的事件分类 1.鼠标事件 click/dblclick/onmouseover/onmouseout 2.HTML事件 onload/onscroll/onsubmit/ ...

  10. JS学习五(js中的事件)

    [JS中的事件分类] 1.鼠标事件 click/bdlclick/onmouseover/onmouseout 2. HTML事件 onload/onscroll/onsubmit/onchange/ ...

随机推荐

  1. CF1166E The LCMs Must be Large

    CF1166E The LCMs Must be Large 构造趣题 正着推其实很不好推 不妨大力猜结论 如果两两集合都有交,那么一定可以 证明: 1.显然如果两个集合没有交,一定不可以 2.否则给 ...

  2. Springboot学习笔记(一)—— 安装

    springboot越来越流行了,相比较于springMVC,springboot采用了一种约定大于配置的理念,可以一键安装,一键运行,一键部署,内置tomcat,省去了一大堆配置的时间,并且,spr ...

  3. linux 不用 ioctl 的设备控制

    有时控制设备最好是通过写控制序列到设备自身来实现. 例如, 这个技术用在控制台驱动 中, 这里所谓的 escape 序列被用来移动光标, 改变缺省的颜色, 或者进行其他的配置任 务. 这样实现设备控制 ...

  4. Java中try catch finally执行

    直接上代码实例: public static void main(String[] args) {    System.out.println(test1()); } static int test1 ...

  5. 51nod 1832 前序后序遍历

    思路:设只有一颗子树的节点有ans个设前序边历数组为pre[100],后序遍历数组为pos[100]:前序遍历的第二个元素是A的一个子节点左右节点不知,设ax-ay表示一个树的前序遍历,bx-by表示 ...

  6. [转载]sublime用法精华

    Sublime Text 全程指南 九月 03.2015. 暂无评论 永远站 作者:Lucida 原文链接:http://lucida.me/blog/sublime-text-complete-gu ...

  7. Maven 运行 tomcat:run 时出现 Unable to compile class for JSP...

    近来无事便去看了看神奇的 Maven , 但写第一个 Hello,World 就非常不友好的怼给我一个 500, 很是郁闷; 开发环境: JDK1.8, Maven 3.5 项目目录: \maven_ ...

  8. wpf passwobox 添加水印

    之前有做过wpf texbox添加水印,这个并不难 重写一下样式就可以了,今天用到了passwordbox 添加水印的时候 发现还是有点难度的. 这个难度就在于如何去取password的长度来控制水印 ...

  9. Qt和c/c++connect函数冲突解决方法

    在使用c/c++的connect函数时在前面写::connect()这样就可以解决了

  10. 关于本地用svn up的时候报cannot update svn folder: "unversioned directory of the same name already exists

    这是因为本地有手动添加过一个文件夹,然后和svn上的同名文件夹重名了,所以无法从svn update下来 解决办法如下: 1.先给本地的重名文件夹改名 mv  dirname repeatdirnam ...