followCameraMouseWheelInput.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { Nullable } from "../../types";
  2. import { serialize } from "../../Misc/decorators";
  3. import { EventState, Observer } from "../../Misc/observable";
  4. import { FollowCamera } from "../../Cameras/followCamera";
  5. import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManager";
  6. import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
  7. /**
  8. * Manage the mouse wheel inputs to control a follow camera.
  9. * @see http://doc.babylonjs.com/how_to/customizing_camera_inputs
  10. */
  11. export class FollowCameraMouseWheelInput implements ICameraInput<FollowCamera> {
  12. /**
  13. * Defines the camera the input is attached to.
  14. */
  15. public camera: FollowCamera;
  16. /**
  17. * Moue wheel controls zoom. (Mouse wheel modifies camera.radius value.)
  18. */
  19. @serialize()
  20. public axisControlRadius: boolean = true;
  21. /**
  22. * Moue wheel controls height. (Mouse wheel modifies camera.heightOffset value.)
  23. */
  24. @serialize()
  25. public axisControlHeight: boolean = false;
  26. /**
  27. * Moue wheel controls angle. (Mouse wheel modifies camera.rotationOffset value.)
  28. */
  29. @serialize()
  30. public axisControlRotation: boolean = false;
  31. /**
  32. * Gets or Set the mouse wheel precision or how fast is the camera moves in
  33. * relation to mouseWheel events.
  34. */
  35. @serialize()
  36. public wheelPrecision = 3.0;
  37. /**
  38. * wheelDeltaPercentage will be used instead of wheelPrecision if different from 0.
  39. * It defines the percentage of current camera.radius to use as delta when wheel is used.
  40. */
  41. @serialize()
  42. public wheelDeltaPercentage = 0;
  43. private _wheel: Nullable<(p: PointerInfo, s: EventState) => void>;
  44. private _observer: Nullable<Observer<PointerInfo>>;
  45. /**
  46. * Attach the input controls to a specific dom element to get the input from.
  47. * @param element Defines the element the controls should be listened from
  48. * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
  49. */
  50. public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
  51. this._wheel = (p, s) => {
  52. // sanity check - this should be a PointerWheel event.
  53. if (p.type !== PointerEventTypes.POINTERWHEEL) { return; }
  54. var event = <MouseWheelEvent>p.event;
  55. var delta = 0;
  56. // Chrome, Safari: event.deltaY
  57. // IE: event.wheelDelta
  58. // Firefox: event.detail (inverted)
  59. var wheelDelta = Math.max(-1, Math.min(1,
  60. (event.deltaY || (<any>event).wheelDelta || -event.detail)));
  61. if (this.wheelDeltaPercentage) {
  62. console.assert((<number>(<unknown>this.axisControlRadius) +
  63. <number>(<unknown>this.axisControlHeight) +
  64. <number>(<unknown>this.axisControlRotation)) <= 1,
  65. "wheelDeltaPercentage only usable when mouse wheel " +
  66. "controlls ONE axis. " +
  67. "Currently enabled: " +
  68. "axisControlRadius: " + this.axisControlRadius +
  69. ", axisControlHeightOffset: " + this.axisControlHeight +
  70. ", axisControlRotationOffset: " + this.axisControlRotation);
  71. if (this.axisControlRadius) {
  72. delta =
  73. wheelDelta * 0.01 * this.wheelDeltaPercentage *
  74. this.camera.radius;
  75. } else if (this.axisControlHeight) {
  76. delta =
  77. wheelDelta * 0.01 * this.wheelDeltaPercentage *
  78. this.camera.heightOffset;
  79. } else if (this.axisControlRotation) {
  80. delta =
  81. wheelDelta * 0.01 * this.wheelDeltaPercentage *
  82. this.camera.rotationOffset;
  83. }
  84. } else {
  85. delta = wheelDelta * this.wheelPrecision;
  86. }
  87. if (delta) {
  88. if (this.axisControlRadius) {
  89. this.camera.radius += delta;
  90. } else if (this.axisControlHeight) {
  91. this.camera.heightOffset -= delta;
  92. } else if (this.axisControlRotation) {
  93. this.camera.rotationOffset -= delta;
  94. }
  95. }
  96. if (event.preventDefault) {
  97. if (!noPreventDefault) {
  98. event.preventDefault();
  99. }
  100. }
  101. };
  102. this._observer = this.camera.getScene().onPointerObservable.add(this._wheel, PointerEventTypes.POINTERWHEEL);
  103. }
  104. /**
  105. * Detach the current controls from the specified dom element.
  106. * @param element Defines the element to stop listening the inputs from
  107. */
  108. public detachControl(element: Nullable<HTMLElement>): void {
  109. if (this._observer && element) {
  110. this.camera.getScene().onPointerObservable.remove(this._observer);
  111. this._observer = null;
  112. this._wheel = null;
  113. }
  114. }
  115. /**
  116. * Gets the class name of the current intput.
  117. * @returns the class name
  118. */
  119. public getClassName(): string {
  120. return "ArcRotateCameraMouseWheelInput";
  121. }
  122. /**
  123. * Get the friendly name associated with the input class.
  124. * @returns the input friendly name
  125. */
  126. public getSimpleName(): string {
  127. return "mousewheel";
  128. }
  129. }
  130. (<any>CameraInputTypes)["FollowCameraMouseWheelInput"] = FollowCameraMouseWheelInput;