diff --git a/src/framework/input/element-input.js b/src/framework/input/element-input.js index 28f81447306..14efa7080a5 100644 --- a/src/framework/input/element-input.js +++ b/src/framework/input/element-input.js @@ -3,7 +3,7 @@ import { Vec3 } from '../../core/math/vec3.js'; import { Vec4 } from '../../core/math/vec4.js'; import { Ray } from '../../core/shape/ray.js'; import { Mouse } from '../../platform/input/mouse.js'; -import { getTouchTargetCoords } from '../../platform/input/touch-event.js'; +import { getTouchTargetCoords, Touch } from '../../platform/input/touch-event.js'; import { getApplication } from '../globals.js'; /** @@ -294,14 +294,14 @@ class ElementTouchEvent extends ElementInputEvent { * * @type {Touch[]} */ - this.touches = event.touches; + this.touches = Array.from(event.touches).map(t => new Touch(t)); /** * The Touch objects representing individual points of contact whose states changed between * the previous touch event and this one. * * @type {Touch[]} */ - this.changedTouches = event.changedTouches; + this.changedTouches = Array.from(event.changedTouches).map(t => new Touch(t)); this.x = x; this.y = y; /** diff --git a/test/framework/input/element-touch-event.test.mjs b/test/framework/input/element-touch-event.test.mjs new file mode 100644 index 00000000000..998eefe08c3 --- /dev/null +++ b/test/framework/input/element-touch-event.test.mjs @@ -0,0 +1,93 @@ +import { expect } from 'chai'; + +import { Entity } from '../../../src/framework/entity.js'; +import { ElementTouchEvent } from '../../../src/framework/input/element-input.js'; +import { Touch } from '../../../src/platform/input/touch-event.js'; +import { createApp } from '../../app.mjs'; +import { jsdomSetup, jsdomTeardown } from '../../jsdom.mjs'; + +describe('ElementTouchEvent', function () { + let app; + + beforeEach(function () { + jsdomSetup(); + app = createApp(); + }); + + afterEach(function () { + app?.destroy(); + app = null; + jsdomTeardown(); + }); + + it('should convert native Touch objects to PlayCanvas Touch objects', function () { + // Ensure HTMLElement is defined in the global scope for jsdom + if (typeof global !== 'undefined' && typeof global.HTMLElement === 'undefined') { + global.HTMLElement = window.HTMLElement; + } + + const screen = new Entity(); + screen.addComponent('screen'); + app.root.addChild(screen); + + const element = new Entity(); + element.addComponent('element'); + screen.addChild(element); + + const camera = new Entity(); + camera.addComponent('camera'); + app.root.addChild(camera); + + // Create mock target element + const targetElement = document.createElement('div'); + document.body.appendChild(targetElement); + + // Create a mock native TouchEvent + const nativeTouchEvent = { + touches: [{ + identifier: 123, + pageX: 100, + pageY: 200, + target: targetElement + }], + changedTouches: [{ + identifier: 456, + pageX: 150, + pageY: 250, + target: targetElement + }] + }; + + const mockTouch = { + identifier: 123, + pageX: 100, + pageY: 200, + target: targetElement + }; + + // Create ElementTouchEvent + const elementTouchEvent = new ElementTouchEvent( + nativeTouchEvent, + element.element, + camera.camera, + 100, + 200, + mockTouch + ); + + // Verify that touches are converted to PlayCanvas Touch objects + expect(elementTouchEvent.touches).to.be.an('array'); + expect(elementTouchEvent.touches.length).to.equal(1); + expect(elementTouchEvent.touches[0]).to.be.instanceof(Touch); + expect(elementTouchEvent.touches[0].id).to.equal(123); + + // Verify that changedTouches are converted to PlayCanvas Touch objects + expect(elementTouchEvent.changedTouches).to.be.an('array'); + expect(elementTouchEvent.changedTouches.length).to.equal(1); + expect(elementTouchEvent.changedTouches[0]).to.be.instanceof(Touch); + expect(elementTouchEvent.changedTouches[0].id).to.equal(456); + + // Verify that the touch object is the same as passed in + expect(elementTouchEvent.touch).to.equal(mockTouch); + }); +});