BaseCameraMouseWheelInput.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import { Nullable } from "../../types";
  2. import { serialize } from "../../Misc/decorators";
  3. import { Observable, Observer } from "../../Misc/observable";
  4. import { Camera } from "../../Cameras/camera";
  5. import { ICameraInput } from "../../Cameras/cameraInputsManager";
  6. import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
  7. import { Tools } from "../../Misc/tools";
  8. /**
  9. * Base class for mouse wheel input..
  10. * See FollowCameraMouseWheelInput in src/Cameras/Inputs/freeCameraMouseWheelInput.ts
  11. * for example usage.
  12. */
  13. export abstract class BaseCameraMouseWheelInput implements ICameraInput<Camera> {
  14. /**
  15. * Defines the camera the input is attached to.
  16. */
  17. public abstract camera: Camera;
  18. /**
  19. * How fast is the camera moves in relation to X axis mouseWheel events.
  20. * Use negative value to reverse direction.
  21. */
  22. @serialize()
  23. public wheelPrecisionX = 3.0;
  24. /**
  25. * How fast is the camera moves in relation to Y axis mouseWheel events.
  26. * Use negative value to reverse direction.
  27. */
  28. @serialize()
  29. public wheelPrecisionY = 3.0;
  30. /**
  31. * How fast is the camera moves in relation to Z axis mouseWheel events.
  32. * Use negative value to reverse direction.
  33. */
  34. @serialize()
  35. public wheelPrecisionZ = 3.0;
  36. /**
  37. * Observable for when a mouse wheel move event occurs.
  38. */
  39. public onChangedObservable = new Observable<{ wheelDeltaX: number; wheelDeltaY: number; wheelDeltaZ: number }>();
  40. private _wheel: Nullable<(pointer: PointerInfo) => void>;
  41. private _observer: Nullable<Observer<PointerInfo>>;
  42. /**
  43. * Attach the input controls to a specific dom element to get the input from.
  44. * @param noPreventDefault Defines whether event caught by the controls
  45. * should call preventdefault().
  46. * (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
  47. */
  48. public attachControl(noPreventDefault?: boolean): void {
  49. noPreventDefault = Tools.BackCompatCameraNoPreventDefault(arguments);
  50. this._wheel = (pointer) => {
  51. // sanity check - this should be a PointerWheel event.
  52. if (pointer.type !== PointerEventTypes.POINTERWHEEL) {
  53. return;
  54. }
  55. const event = <MouseWheelEvent>pointer.event;
  56. const platformScale = event.deltaMode === WheelEvent.DOM_DELTA_LINE ? this._ffMultiplier : 1;
  57. if (event.deltaY !== undefined) {
  58. // Most recent browsers versions have delta properties.
  59. // Firefox >= v17 (Has WebGL >= v4)
  60. // Chrome >= v31 (Has WebGL >= v8)
  61. // Edge >= v12 (Has WebGl >= v12)
  62. // https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
  63. this._wheelDeltaX += (this.wheelPrecisionX * platformScale * event.deltaX) / this._normalize;
  64. this._wheelDeltaY -= (this.wheelPrecisionY * platformScale * event.deltaY) / this._normalize;
  65. this._wheelDeltaZ += (this.wheelPrecisionZ * platformScale * event.deltaZ) / this._normalize;
  66. } else if ((<any>event).wheelDeltaY !== undefined) {
  67. // Unsure whether these catch anything more. Documentation
  68. // online is contradictory.
  69. this._wheelDeltaX += (this.wheelPrecisionX * platformScale * (<any>event).wheelDeltaX) / this._normalize;
  70. this._wheelDeltaY -= (this.wheelPrecisionY * platformScale * (<any>event).wheelDeltaY) / this._normalize;
  71. this._wheelDeltaZ += (this.wheelPrecisionZ * platformScale * (<any>event).wheelDeltaZ) / this._normalize;
  72. } else if ((<any>event).wheelDelta) {
  73. // IE >= v9 (Has WebGL >= v11)
  74. // Maybe others?
  75. this._wheelDeltaY -= (this.wheelPrecisionY * (<any>event).wheelDelta) / this._normalize;
  76. }
  77. if (event.preventDefault) {
  78. if (!noPreventDefault) {
  79. event.preventDefault();
  80. }
  81. }
  82. };
  83. this._observer = this.camera.getScene().onPointerObservable.add(this._wheel, PointerEventTypes.POINTERWHEEL);
  84. }
  85. /**
  86. * Detach the current controls from the specified dom element.
  87. */
  88. public detachControl(): void;
  89. /**
  90. * Detach the current controls from the specified dom element.
  91. * @param ignored defines an ignored parameter kept for backward compatibility. If you want to define the source input element, you can set engine.inputElement before calling camera.attachControl
  92. */
  93. public detachControl(ignored?: any): void {
  94. if (this._observer) {
  95. this.camera.getScene().onPointerObservable.remove(this._observer);
  96. this._observer = null;
  97. this._wheel = null;
  98. }
  99. if (this.onChangedObservable) {
  100. this.onChangedObservable.clear();
  101. }
  102. }
  103. /**
  104. * Called for each rendered frame.
  105. */
  106. public checkInputs(): void {
  107. this.onChangedObservable.notifyObservers({
  108. wheelDeltaX: this._wheelDeltaX,
  109. wheelDeltaY: this._wheelDeltaY,
  110. wheelDeltaZ: this._wheelDeltaZ,
  111. });
  112. // Clear deltas.
  113. this._wheelDeltaX = 0;
  114. this._wheelDeltaY = 0;
  115. this._wheelDeltaZ = 0;
  116. }
  117. /**
  118. * Gets the class name of the current intput.
  119. * @returns the class name
  120. */
  121. public getClassName(): string {
  122. return "BaseCameraMouseWheelInput";
  123. }
  124. /**
  125. * Get the friendly name associated with the input class.
  126. * @returns the input friendly name
  127. */
  128. public getSimpleName(): string {
  129. return "mousewheel";
  130. }
  131. /**
  132. * Incremental value of multiple mouse wheel movements of the X axis.
  133. * Should be zero-ed when read.
  134. */
  135. protected _wheelDeltaX: number = 0;
  136. /**
  137. * Incremental value of multiple mouse wheel movements of the Y axis.
  138. * Should be zero-ed when read.
  139. */
  140. protected _wheelDeltaY: number = 0;
  141. /**
  142. * Incremental value of multiple mouse wheel movements of the Z axis.
  143. * Should be zero-ed when read.
  144. */
  145. protected _wheelDeltaZ: number = 0;
  146. /**
  147. * Firefox uses a different scheme to report scroll distances to other
  148. * browsers. Rather than use complicated methods to calculate the exact
  149. * multiple we need to apply, let's just cheat and use a constant.
  150. * https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode
  151. * https://stackoverflow.com/questions/20110224/what-is-the-height-of-a-line-in-a-wheel-event-deltamode-dom-delta-line
  152. */
  153. private readonly _ffMultiplier = 12;
  154. /**
  155. * Different event attributes for wheel data fall into a few set ranges.
  156. * Some relevant but dated date here:
  157. * https://stackoverflow.com/questions/5527601/normalizing-mousewheel-speed-across-browsers
  158. */
  159. private readonly _normalize = 120;
  160. }