Control.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import {
  2. Raycaster,
  3. Vector2,
  4. Sprite,
  5. Math as ThreeMath
  6. } from 'three';
  7. import {render} from './Render.js';
  8. import Constant from './Constant.js';
  9. import {modelManager} from './ModelManager.js';
  10. export default class Control{
  11. constructor(scene,camera){
  12. this.scene = scene;
  13. this.camera = camera;
  14. this.selectModel = null;
  15. this.arrowControls = null;
  16. this.onDownPosition = null;
  17. this.onUpPosition = null;
  18. this.dragging = false;
  19. this.raycaster = new Raycaster();
  20. this.init();
  21. }
  22. init(){
  23. this.bindEvents();
  24. }
  25. bindEvents(){
  26. document.addEventListener('pointermove', this.onPointerMove.bind(this));
  27. document.addEventListener('pointerdown', this.onPointerDown.bind(this));
  28. document.addEventListener('pointerup', this.onPointerUp.bind(this));
  29. }
  30. onPointerMove( event ) {
  31. let pointer = new Vector2();
  32. pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  33. pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  34. this.setSelectModel(pointer);
  35. }
  36. onPointerDown( event ) {
  37. this.onDownPosition = new Vector2();
  38. this.onDownPosition.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  39. this.onDownPosition.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  40. this.dragging = true;
  41. }
  42. onPointerUp( event ) {
  43. this.onUpPosition = new Vector2();
  44. this.onUpPosition.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  45. this.onUpPosition.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  46. this.handleClick();
  47. this.dragging = false;
  48. }
  49. setSelectModel(pointer){
  50. // 通过摄像机和鼠标位置更新射线
  51. this.raycaster.setFromCamera( pointer, this.camera );
  52. // 计算物体和射线的焦点
  53. var intersects = this.raycaster.intersectObjects( this.scene.children );
  54. if(intersects && intersects[0])
  55. {
  56. for(let i=0;i<intersects.length;++i){
  57. let model = intersects[i].object;
  58. //if(model.type == "TransformControlsPlane"){
  59. if(model.type != "Mesh"&&model.type != "Group"&&model.type != 'Point'){
  60. continue;
  61. }
  62. if(model.parent && model.parent.type === "Group"){
  63. while(model.parent && model.parent.type === "Group"){
  64. model = model.parent;
  65. }
  66. }
  67. if(modelManager.tilesMeshesUUIDs.indexOf(model.uuid) == -1&&modelManager.meshesUUIDs.indexOf(model.uuid) == -1&&modelManager.pointMeshesUUIDs.indexOf(model.uuid) == -1)
  68. {
  69. continue;
  70. }
  71. if(this.selectModel == null){
  72. this.selectModel = model;
  73. //选中
  74. render.updateSelectModel(this.selectModel,true);
  75. }
  76. else if(this.selectModel.uuid == model.uuid){
  77. render.updateSelectModel(this.selectModel,true);
  78. }
  79. else if(this.selectModel.uuid != model.uuid){
  80. //恢复
  81. render.updateSelectModel(this.selectModel,false);
  82. this.selectModel = model;
  83. //选中
  84. render.updateSelectModel(this.selectModel,true);
  85. }
  86. return ;
  87. }
  88. }
  89. render.updateSelectModel(this.selectModel,false);
  90. this.selectModel = null;
  91. }
  92. /*
  93. selectObjects(pointer){
  94. // 通过摄像机和鼠标位置更新射线
  95. this.raycaster.setFromCamera( pointer, this.camera );
  96. // 计算物体和射线的焦点
  97. var intersects = this.raycaster.intersectObjects( this.scene.children );
  98. if(intersects && intersects[0])
  99. {
  100. let model = intersects[0].object;
  101. if(model.parent && model.parent.type === "Group"){
  102. while(model.parent && model.parent.type === "Group"){
  103. model = model.parent;
  104. }
  105. }
  106. Constant.tilesMaterial.color.set( 0xff0000 );
  107. }
  108. // for ( var i = 0; i < intersects.length; i++ ) {
  109. // intersects[ i ].object.material.color.set( 0xff0000 );
  110. // }
  111. }
  112. */
  113. onDocumentTouchStart( event ) {
  114. //通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作)
  115. event.preventDefault();
  116. /*
  117. html的坐标轴是以左上角为(0,0),右下方向为正方向
  118. event.clientX=event.pageX返回当事件被触发时鼠标指针向对于浏览器可见区域的X坐标
  119. event.offsetX返回当前事件相对于事件源元素(srcElement)的X坐标
  120. event.screenX鼠标相对于用户显示器屏幕左上角的X坐标
  121. */
  122. event.clientX = event.touches[0].clientX;
  123. event.clientY = event.touches[0].clientY;
  124. this.onDocumentMouseDown( event );
  125. }
  126. onDocumentMouseDown( event ) {
  127. event.preventDefault();
  128. /*
  129. mouse.x = (2 * event.clientX - renderer.domElement.clientWidth) / renderer.domElement.clientWidth
  130. mouse.y = (renderer.domElement.clientHeight - 2 * event.clientY) / renderer.domElement.clientHeight
  131. 鼠标位置在一个边长为2的正方形内部,正方形中心为(0,0)点
  132. 因此,mouse.x和mouse.y的取值范围是[-1,1]
  133. */
  134. mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
  135. mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
  136. //设置该射线从相机位置发出,射向视场的鼠标位置
  137. raycaster.setFromCamera( mouse, camera );
  138. //判断射线是否穿过这些物体,参数是数组。返回的是与射线相交的结果数组,按距离从近到远有序排列
  139. var intersects = raycaster.intersectObjects( objects );
  140. if ( intersects.length > 0 ) {
  141. /*
  142. intersects[ 0 ] {
  143. distance: double
  144. face: Face3
  145. faceIndex: int
  146. object: Mesh
  147. point: Vector3
  148. uv: Vector2
  149. __proto__: Object
  150. }
  151. */
  152. //intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
  153. var particle = new Sprite( particleMaterial );
  154. //vector3不能直接用"等号"赋值。只能用copy进行复制。set方法需要分别传递x,y,z三个标量
  155. particle.position.copy( intersects[ 0 ].point );
  156. particle.scale.x = particle.scale.y = 16;
  157. scene.add( particle );
  158. }
  159. // Parse all the faces
  160. for ( var i in intersects ) {
  161. //这句已经无效了,因为face下面不存在material,face下存在color,但是即使改变color也改变不了面的颜色
  162. //intersects[ i ].face.material[ 0 ].color.setHex( Math.random() * 0xffffff | 0x80000000 );
  163. intersects[ i ].object.material.color.setHex( Math.random() * Constant.defaultColor );
  164. }
  165. }
  166. handleClick(){
  167. if ( this.selectModel != null && this.onDownPosition.distanceTo( this.onUpPosition ) === 0 ) {
  168. this.arrowControls.attach( this.selectModel );
  169. this.arrowControls.setMode('translate');
  170. //this.arrowControls.setMode('rotate');
  171. }
  172. else if(this.selectModel == null && this.onDownPosition.distanceTo( this.onUpPosition ) === 0){
  173. this.arrowControls.detach( );
  174. }
  175. this.onDownPosition = new Vector2();
  176. this.onUpPosition = new Vector2();
  177. }
  178. }