arcRotateCameraMouseWheelInput.ts 5.1 KB

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