From 80cdf3771982a5e931c4ce2a8e2298d8fcf0df47 Mon Sep 17 00:00:00 2001 From: Will Eastcott Date: Sun, 10 Mar 2024 11:30:19 +0000 Subject: [PATCH] Refactor input-related code --- src/platform/input/keyboard-event.js | 40 ++++--- src/platform/input/keyboard.js | 14 ++- src/platform/input/mouse-event.js | 171 +++++++++++++++------------ src/platform/input/mouse.js | 52 ++++---- src/platform/input/touch-event.js | 138 +++++++++++---------- 5 files changed, 225 insertions(+), 190 deletions(-) diff --git a/src/platform/input/keyboard-event.js b/src/platform/input/keyboard-event.js index d209a213e52..2c605befc65 100644 --- a/src/platform/input/keyboard-event.js +++ b/src/platform/input/keyboard-event.js @@ -5,6 +5,27 @@ * @category Input */ class KeyboardEvent { + /** + * The keyCode of the key that has changed. See the KEY_* constants. + * + * @type {number|null} + */ + key = null; + + /** + * The element that fired the keyboard event. + * + * @type {Element|null} + */ + element = null; + + /** + * The original browser event which was fired. + * + * @type {globalThis.KeyboardEvent|null} + */ + event = null; + /** * Create a new KeyboardEvent. * @@ -22,28 +43,9 @@ class KeyboardEvent { */ constructor(keyboard, event) { if (event) { - /** - * The keyCode of the key that has changed. See the KEY_* constants. - * - * @type {number} - */ this.key = event.keyCode; - /** - * The element that fired the keyboard event. - * - * @type {Element} - */ this.element = event.target; - /** - * The original browser event which was fired. - * - * @type {globalThis.KeyboardEvent} - */ this.event = event; - } else { - this.key = null; - this.element = null; - this.event = null; } } } diff --git a/src/platform/input/keyboard.js b/src/platform/input/keyboard.js index 907e5ffe931..404ea3391db 100644 --- a/src/platform/input/keyboard.js +++ b/src/platform/input/keyboard.js @@ -92,6 +92,15 @@ class Keyboard extends EventHandler { */ static EVENT_KEYUP = 'keyup'; + /** @private */ + _element = null; + + /** @private */ + _keymap = {}; + + /** @private */ + _lastmap = {}; + /** * Create a new Keyboard instance. * @@ -113,17 +122,12 @@ class Keyboard extends EventHandler { constructor(element, options = {}) { super(); - this._element = null; - this._keyDownHandler = this._handleKeyDown.bind(this); this._keyUpHandler = this._handleKeyUp.bind(this); this._keyPressHandler = this._handleKeyPress.bind(this); this._visibilityChangeHandler = this._handleVisibilityChange.bind(this); this._windowBlurHandler = this._handleWindowBlur.bind(this); - this._keymap = {}; - this._lastmap = {}; - if (element) { this.attach(element); } diff --git a/src/platform/input/mouse-event.js b/src/platform/input/mouse-event.js index 8176449cbf3..8ba068e3531 100644 --- a/src/platform/input/mouse-event.js +++ b/src/platform/input/mouse-event.js @@ -16,11 +16,100 @@ function isMousePointerLocked() { * @category Input */ class MouseEvent { + /** + * The x coordinate of the mouse pointer relative to the element {@link Mouse} is attached to. + * + * @type {number} + */ + x = 0; + + /** + * The y coordinate of the mouse pointer relative to the element {@link Mouse} is attached to. + * + * @type {number} + */ + y = 0; + + /** + * The change in x coordinate since the last mouse event. + * + * @type {number} + */ + dx = 0; + + /** + * The change in y coordinate since the last mouse event. + * + * @type {number} + */ + dy = 0; + + /** + * The mouse button associated with this event. Can be: + * + * - {@link MOUSEBUTTON_LEFT} + * - {@link MOUSEBUTTON_MIDDLE} + * - {@link MOUSEBUTTON_RIGHT} + * + * @type {number} + */ + button = MOUSEBUTTON_NONE; + + /** + * A value representing the amount the mouse wheel has moved, only valid for + * {@link EVENT_MOUSEWHEEL} events. + * + * @type {number} + */ + wheelDelta = 0; + + /** + * The element that the mouse was fired from. + * + * @type {Element} + */ + element; + + /** + * True if the ctrl key was pressed when this event was fired. + * + * @type {boolean} + */ + ctrlKey = false; + + /** + * True if the alt key was pressed when this event was fired. + * + * @type {boolean} + */ + altKey = false; + + /** + * True if the shift key was pressed when this event was fired. + * + * @type {boolean} + */ + shiftKey = false; + + /** + * True if the meta key was pressed when this event was fired. + * + * @type {boolean} + */ + metaKey = false; + + /** + * The original browser event. + * + * @type {globalThis.MouseEvent|globalThis.WheelEvent} + */ + event; + /** * Create a new MouseEvent instance. * * @param {import('./mouse.js').Mouse} mouse - The Mouse device that is firing this event. - * @param {globalThis.MouseEvent} event - The original browser event that fired. + * @param {globalThis.MouseEvent|globalThis.WheelEvent} event - The original browser event that fired. */ constructor(mouse, event) { let coords = { @@ -38,19 +127,7 @@ class MouseEvent { } if (coords) { - /** - * The x coordinate of the mouse pointer relative to the element {@link Mouse} is - * attached to. - * - * @type {number} - */ this.x = coords.x; - /** - * The y coordinate of the mouse pointer relative to the element {@link Mouse} is - * attached to. - * - * @type {number} - */ this.y = coords.y; } else if (isMousePointerLocked()) { this.x = 0; @@ -59,13 +136,6 @@ class MouseEvent { return; } - /** - * A value representing the amount the mouse wheel has moved, only valid for - * {@link EVENT_MOUSEWHEEL} events. - * - * @type {number} - */ - this.wheelDelta = 0; // deltaY is in a different range across different browsers. The only thing // that is consistent is the sign of the value so snap to -1/+1. if (event.type === 'wheel') { @@ -78,17 +148,7 @@ class MouseEvent { // Get the movement delta in this event if (isMousePointerLocked()) { - /** - * The change in x coordinate since the last mouse event. - * - * @type {number} - */ this.dx = event.movementX || event.webkitMovementX || event.mozMovementX || 0; - /** - * The change in y coordinate since the last mouse event. - * - * @type {number} - */ this.dy = event.movementY || event.webkitMovementY || event.mozMovementY || 0; } else { this.dx = this.x - mouse._lastX; @@ -96,58 +156,17 @@ class MouseEvent { } if (event.type === 'mousedown' || event.type === 'mouseup') { - /** - * The mouse button associated with this event. Can be: - * - * - {@link MOUSEBUTTON_LEFT} - * - {@link MOUSEBUTTON_MIDDLE} - * - {@link MOUSEBUTTON_RIGHT} - * - * @type {number} - */ this.button = event.button; - } else { - this.button = MOUSEBUTTON_NONE; } this.buttons = mouse._buttons.slice(0); - /** - * The element that the mouse was fired from. - * - * @type {Element} - */ this.element = event.target; - /** - * True if the ctrl key was pressed when this event was fired. - * - * @type {boolean} - */ - this.ctrlKey = event.ctrlKey || false; - /** - * True if the alt key was pressed when this event was fired. - * - * @type {boolean} - */ - this.altKey = event.altKey || false; - /** - * True if the shift key was pressed when this event was fired. - * - * @type {boolean} - */ - this.shiftKey = event.shiftKey || false; - /** - * True if the meta key was pressed when this event was fired. - * - * @type {boolean} - */ - this.metaKey = event.metaKey || false; - - /** - * The original browser event. - * - * @type {globalThis.MouseEvent} - */ + this.ctrlKey = event.ctrlKey ?? false; + this.altKey = event.altKey ?? false; + this.shiftKey = event.shiftKey ?? false; + this.metaKey = event.metaKey ?? false; + this.event = event; } } diff --git a/src/platform/input/mouse.js b/src/platform/input/mouse.js index 20b80af6b0d..a4b47ad502d 100644 --- a/src/platform/input/mouse.js +++ b/src/platform/input/mouse.js @@ -61,6 +61,24 @@ class Mouse extends EventHandler { */ static EVENT_MOUSEWHEEL = EVENT_MOUSEWHEEL; + /** @private */ + _lastX = 0; + + /** @private */ + _lastY = 0; + + /** @private */ + _buttons = [false, false, false]; + + /** @private */ + _lastbuttons = [false, false, false]; + + /** @private */ + _target = null; + + /** @private */ + _attached = false; + /** * Create a new Mouse instance. * @@ -69,13 +87,6 @@ class Mouse extends EventHandler { constructor(element) { super(); - // Clear the mouse state - this._lastX = 0; - this._lastY = 0; - this._buttons = [false, false, false]; - this._lastbuttons = [false, false, false]; - - // Setup event handlers so they are bound to the correct 'this' this._upHandler = this._handleUp.bind(this); this._downHandler = this._handleDown.bind(this); @@ -85,9 +96,6 @@ class Mouse extends EventHandler { event.preventDefault(); }; - this._target = null; - this._attached = false; - this.attach(element); } @@ -111,11 +119,13 @@ class Mouse extends EventHandler { if (this._attached) return; this._attached = true; - const opts = platform.passiveEvents ? { passive: false } : false; - window.addEventListener('mouseup', this._upHandler, opts); - window.addEventListener('mousedown', this._downHandler, opts); - window.addEventListener('mousemove', this._moveHandler, opts); - window.addEventListener('wheel', this._wheelHandler, opts); + /** @type {AddEventListenerOptions} */ + const passiveOptions = { passive: false }; + const options = platform.passiveEvents ? passiveOptions : false; + window.addEventListener('mouseup', this._upHandler, options); + window.addEventListener('mousedown', this._downHandler, options); + window.addEventListener('mousemove', this._moveHandler, options); + window.addEventListener('wheel', this._wheelHandler, options); } /** @@ -126,11 +136,13 @@ class Mouse extends EventHandler { this._attached = false; this._target = null; - const opts = platform.passiveEvents ? { passive: false } : false; - window.removeEventListener('mouseup', this._upHandler, opts); - window.removeEventListener('mousedown', this._downHandler, opts); - window.removeEventListener('mousemove', this._moveHandler, opts); - window.removeEventListener('wheel', this._wheelHandler, opts); + /** @type {AddEventListenerOptions} */ + const passiveOptions = { passive: false }; + const options = platform.passiveEvents ? passiveOptions : false; + window.removeEventListener('mouseup', this._upHandler, options); + window.removeEventListener('mousedown', this._downHandler, options); + window.removeEventListener('mousemove', this._moveHandler, options); + window.removeEventListener('wheel', this._wheelHandler, options); } /** diff --git a/src/platform/input/touch-event.js b/src/platform/input/touch-event.js index 72ebe6398fc..cc4a2ef0162 100644 --- a/src/platform/input/touch-event.js +++ b/src/platform/input/touch-event.js @@ -34,6 +34,41 @@ function getTouchTargetCoords(touch) { * @category Input */ class Touch { + /** + * The identifier of the touch. + * + * @type {number} + */ + id; + + /** + * The x coordinate relative to the element that the TouchDevice is attached to. + * + * @type {number} + */ + x; + + /** + * The y coordinate relative to the element that the TouchDevice is attached to. + * + * @type {number} + */ + y; + + /** + * The target DOM element of the touch event. + * + * @type {Element} + */ + target; + + /** + * The original browser Touch object. + * + * @type {globalThis.Touch} + */ + touch; + /** * Create a new Touch object from the browser Touch. * @@ -42,38 +77,10 @@ class Touch { constructor(touch) { const coords = getTouchTargetCoords(touch); - /** - * The identifier of the touch. - * - * @type {number} - */ this.id = touch.identifier; - - /** - * The x coordinate relative to the element that the TouchDevice is attached to. - * - * @type {number} - */ this.x = coords.x; - /** - * The y coordinate relative to the element that the TouchDevice is attached to. - * - * @type {number} - */ this.y = coords.y; - - /** - * The target DOM element of the touch event. - * - * @type {Element} - */ this.target = touch.target; - - /** - * The original browser Touch object. - * - * @type {globalThis.Touch} - */ this.touch = touch; } } @@ -85,6 +92,34 @@ class Touch { * @category Input */ class TouchEvent { + /** + * The target DOM element that the event was fired from. + * + * @type {Element} + */ + element; + + /** + * The original browser TouchEvent. + * + * @type {globalThis.TouchEvent} + */ + event; + + /** + * A list of all touches currently in contact with the device. + * + * @type {Touch[]} + */ + touches = []; + + /** + * A list of touches that have changed since the last event. + * + * @type {Touch[]} + */ + changedTouches = []; + /** * Create a new TouchEvent instance. It is created from an existing browser event. * @@ -93,42 +128,11 @@ class TouchEvent { * @param {globalThis.TouchEvent} event - The original browser TouchEvent. */ constructor(device, event) { - /** - * The target DOM element that the event was fired from. - * - * @type {Element} - */ this.element = event.target; - /** - * The original browser TouchEvent. - * - * @type {globalThis.TouchEvent} - */ this.event = event; - /** - * A list of all touches currently in contact with the device. - * - * @type {Touch[]} - */ - this.touches = []; - /** - * A list of touches that have changed since the last event. - * - * @type {Touch[]} - */ - this.changedTouches = []; - - if (event) { - for (let i = 0, l = event.touches.length; i < l; i++) { - this.touches.push(new Touch(event.touches[i])); - } - - - for (let i = 0, l = event.changedTouches.length; i < l; i++) { - this.changedTouches.push(new Touch(event.changedTouches[i])); - } - } + this.touches = Array.from(event.touches).map(touch => new Touch(touch)); + this.changedTouches = Array.from(event.changedTouches).map(touch => new Touch(touch)); } /** @@ -136,17 +140,11 @@ class TouchEvent { * id so that you can be sure you are referencing the same touch. * * @param {number} id - The identifier of the touch. - * @param {Touch[]|null} list - An array of touches to search. - * @returns {Touch} The {@link Touch} object or null. + * @param {Touch[]} list - An array of touches to search. + * @returns {Touch|null} The {@link Touch} object or null. */ getTouchById(id, list) { - for (let i = 0, l = list.length; i < l; i++) { - if (list[i].id === id) { - return list[i]; - } - } - - return null; + return list.find(touch => touch.id === id) || null; } }