InteractiveGroup.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import {
  2. Group,
  3. Raycaster,
  4. Vector2
  5. } from 'three';
  6. const _pointer = new Vector2();
  7. const _event = { type: '', data: _pointer };
  8. // TODO: Dispatch pointerevents too
  9. /**
  10. * The XR events that are mapped to "standard" pointer events
  11. */
  12. const _events = {
  13. 'move': 'mousemove',
  14. 'select': 'click',
  15. 'selectstart': 'mousedown',
  16. 'selectend': 'mouseup'
  17. };
  18. const _raycaster = new Raycaster();
  19. class InteractiveGroup extends Group {
  20. constructor() {
  21. super();
  22. this.raycaster = new Raycaster();
  23. this.element = null;
  24. this.camera = null;
  25. this.controllers = [];
  26. this._onPointerEvent = this.onPointerEvent.bind( this );
  27. this._onXRControllerEvent = this.onXRControllerEvent.bind( this );
  28. }
  29. onPointerEvent( event ) {
  30. event.stopPropagation();
  31. const rect = this.element.getBoundingClientRect();
  32. _pointer.x = ( event.clientX - rect.left ) / rect.width * 2 - 1;
  33. _pointer.y = - ( event.clientY - rect.top ) / rect.height * 2 + 1;
  34. this.raycaster.setFromCamera( _pointer, this.camera );
  35. const intersects = this.raycaster.intersectObjects( this.children, false );
  36. if ( intersects.length > 0 ) {
  37. const intersection = intersects[ 0 ];
  38. const object = intersection.object;
  39. const uv = intersection.uv;
  40. _event.type = event.type;
  41. _event.data.set( uv.x, 1 - uv.y );
  42. object.dispatchEvent( _event );
  43. }
  44. }
  45. onXRControllerEvent( event ) {
  46. const controller = event.target;
  47. _raycaster.setFromXRController( controller );
  48. const intersections = _raycaster.intersectObjects( this.children, false );
  49. if ( intersections.length > 0 ) {
  50. const intersection = intersections[ 0 ];
  51. const object = intersection.object;
  52. const uv = intersection.uv;
  53. _event.type = _events[ event.type ];
  54. _event.data.set( uv.x, 1 - uv.y );
  55. object.dispatchEvent( _event );
  56. }
  57. }
  58. listenToPointerEvents( renderer, camera ) {
  59. this.camera = camera;
  60. this.element = renderer.domElement;
  61. this.element.addEventListener( 'pointerdown', this._onPointerEvent );
  62. this.element.addEventListener( 'pointerup', this._onPointerEvent );
  63. this.element.addEventListener( 'pointermove', this._onPointerEvent );
  64. this.element.addEventListener( 'mousedown', this._onPointerEvent );
  65. this.element.addEventListener( 'mouseup', this._onPointerEvent );
  66. this.element.addEventListener( 'mousemove', this._onPointerEvent );
  67. this.element.addEventListener( 'click', this._onPointerEvent );
  68. }
  69. disconnectionPointerEvents() {
  70. if ( this.element !== null ) {
  71. this.element.removeEventListener( 'pointerdown', this._onPointerEvent );
  72. this.element.removeEventListener( 'pointerup', this._onPointerEvent );
  73. this.element.removeEventListener( 'pointermove', this._onPointerEvent );
  74. this.element.removeEventListener( 'mousedown', this._onPointerEvent );
  75. this.element.removeEventListener( 'mouseup', this._onPointerEvent );
  76. this.element.removeEventListener( 'mousemove', this._onPointerEvent );
  77. this.element.removeEventListener( 'click', this._onPointerEvent );
  78. }
  79. }
  80. listenToXRControllerEvents( controller ) {
  81. this.controllers.push( controller );
  82. controller.addEventListener( 'move', this._onXRControllerEvent );
  83. controller.addEventListener( 'select', this._onXRControllerEvent );
  84. controller.addEventListener( 'selectstart', this._onXRControllerEvent );
  85. controller.addEventListener( 'selectend', this._onXRControllerEvent );
  86. }
  87. disconnectXrControllerEvents() {
  88. for ( const controller of this.controllers ) {
  89. controller.removeEventListener( 'move', this._onXRControllerEvent );
  90. controller.removeEventListener( 'select', this._onXRControllerEvent );
  91. controller.removeEventListener( 'selectstart', this._onXRControllerEvent );
  92. controller.removeEventListener( 'selectend', this._onXRControllerEvent );
  93. }
  94. }
  95. disconnect() {
  96. this.disconnectionPointerEvents();
  97. this.disconnectXrControllerEvents();
  98. this.camera = null;
  99. this.element = null;
  100. this.controllers = [];
  101. }
  102. }
  103. export { InteractiveGroup };
粤ICP备19079148号