arcRotateCameraMouseWheelInput.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { Nullable } from "../../types";
  2. import { serialize } from "../../Misc/decorators";
  3. import { EventState, Observer } from "../../Misc/observable";
  4. import { ArcRotateCamera } from "../../Cameras/arcRotateCamera";
  5. import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManager";
  6. import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
  7. import { Scalar } from '../../Maths/math.scalar';
  8. import { Tools } from '../../Misc/tools';
  9. /**
  10. * Manage the mouse wheel inputs to control an arc rotate camera.
  11. * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
  12. */
  13. export class ArcRotateCameraMouseWheelInput implements ICameraInput<ArcRotateCamera> {
  14. /**
  15. * Defines the camera the input is attached to.
  16. */
  17. public camera: ArcRotateCamera;
  18. /**
  19. * Gets or Set the mouse wheel precision or how fast is the camera zooming.
  20. */
  21. @serialize()
  22. public wheelPrecision = 3.0;
  23. /**
  24. * wheelDeltaPercentage will be used instead of wheelPrecision if different from 0.
  25. * It defines the percentage of current camera.radius to use as delta when wheel is used.
  26. */
  27. @serialize()
  28. public wheelDeltaPercentage = 0;
  29. private _wheel: Nullable<(p: PointerInfo, s: EventState) => void>;
  30. private _observer: Nullable<Observer<PointerInfo>>;
  31. private computeDeltaFromMouseWheelLegacyEvent(mouseWheelDelta: number, radius: number) {
  32. var delta = 0;
  33. var wheelDelta = (mouseWheelDelta * 0.01 * this.wheelDeltaPercentage) * radius;
  34. if (mouseWheelDelta > 0) {
  35. delta = wheelDelta / (1.0 + this.wheelDeltaPercentage);
  36. } else {
  37. delta = wheelDelta * (1.0 + this.wheelDeltaPercentage);
  38. }
  39. return delta;
  40. }
  41. /**
  42. * Attach the input controls to a specific dom element to get the input from.
  43. * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
  44. */
  45. public attachControl(noPreventDefault?: boolean): void {
  46. // was there a second variable defined?
  47. noPreventDefault = Tools.BackCompatCameraNoPreventDefault(arguments);
  48. this._wheel = (p, s) => {
  49. //sanity check - this should be a PointerWheel event.
  50. if (p.type !== PointerEventTypes.POINTERWHEEL) { return; }
  51. var event = <MouseWheelEvent>p.event;
  52. var delta = 0;
  53. let mouseWheelLegacyEvent = event as any;
  54. let wheelDelta = 0;
  55. if (mouseWheelLegacyEvent.wheelDelta) {
  56. wheelDelta = mouseWheelLegacyEvent.wheelDelta;
  57. } else {
  58. wheelDelta = -(event.deltaY || event.detail) * 60;
  59. }
  60. if (this.wheelDeltaPercentage) {
  61. delta = this.computeDeltaFromMouseWheelLegacyEvent(wheelDelta, this.camera.radius);
  62. // If zooming in, estimate the target radius and use that to compute the delta for inertia
  63. // this will stop multiple scroll events zooming in from adding too much inertia
  64. if (delta > 0) {
  65. var estimatedTargetRadius = this.camera.radius;
  66. var targetInertia = this.camera.inertialRadiusOffset + delta;
  67. for (var i = 0; i < 20 && Math.abs(targetInertia) > 0.001; i++) {
  68. estimatedTargetRadius -= targetInertia;
  69. targetInertia *= this.camera.inertia;
  70. }
  71. estimatedTargetRadius = Scalar.Clamp(estimatedTargetRadius, 0, Number.MAX_VALUE);
  72. delta = this.computeDeltaFromMouseWheelLegacyEvent(wheelDelta, estimatedTargetRadius);
  73. }
  74. } else {
  75. delta = wheelDelta / (this.wheelPrecision * 40);
  76. }
  77. if (delta) {
  78. this.camera.inertialRadiusOffset += delta;
  79. }
  80. if (event.preventDefault) {
  81. if (!noPreventDefault) {
  82. event.preventDefault();
  83. }
  84. }
  85. };
  86. this._observer = this.camera.getScene().onPointerObservable.add(this._wheel, PointerEventTypes.POINTERWHEEL);
  87. }
  88. /**
  89. * Detach the current controls from the specified dom element.
  90. */
  91. public detachControl(): void;
  92. /**
  93. * Detach the current controls from the specified dom element.
  94. * @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
  95. */
  96. public detachControl(ignored?: any): void {
  97. if (this._observer) {
  98. this.camera.getScene().onPointerObservable.remove(this._observer);
  99. this._observer = null;
  100. this._wheel = null;
  101. }
  102. }
  103. /**
  104. * Gets the class name of the current input.
  105. * @returns the class name
  106. */
  107. public getClassName(): string {
  108. return "ArcRotateCameraMouseWheelInput";
  109. }
  110. /**
  111. * Get the friendly name associated with the input class.
  112. * @returns the input friendly name
  113. */
  114. public getSimpleName(): string {
  115. return "mousewheel";
  116. }
  117. }
  118. (<any>CameraInputTypes)["ArcRotateCameraMouseWheelInput"] = ArcRotateCameraMouseWheelInput;