UNPKG

unreal-html5-touch-controller

Version:

Touch controller for Unreal Engine HTML5 exports with joystick and gesture support.

91 lines (78 loc) 2.44 kB
export class CanvasViewControl { constructor(canvasId, region) { this.canvas = document.getElementById(canvasId); if (!this.canvas) { console.warn(`[UnrealHTML5TouchController] Canvas not found with id "${canvasId}"`); return; } this.viewTouchId = null; this.lastTouch = null; // Accept 0~1 number or a custom function this.touchRegion = typeof region === 'function' ? region : (x) => x > window.innerWidth * region; this._styleCanvas(); this._bindEvents(); } _styleCanvas() { this.canvas.style.touchAction = 'none'; const body = document.body; body.style.overflow = 'hidden'; body.style.position = 'fixed'; body.style.width = '100%'; body.style.height = '100%'; body.style.touchAction = 'none'; // Enable canvas to receive focus and keyboard events this.canvas.setAttribute('tabindex', '0'); this.canvas.focus(); } _bindEvents() { this.canvas.addEventListener("touchstart", this._onTouchStart.bind(this), { passive: false }); this.canvas.addEventListener("touchmove", this._onTouchMove.bind(this), { passive: false }); this.canvas.addEventListener("touchend", this._onTouchEnd.bind(this), { passive: false }); } _onTouchStart(e) { for (const touch of e.changedTouches) { if (touch.clientX > window.innerWidth / 2) { this.viewTouchId = touch.identifier; this.lastTouch = { x: touch.clientX, y: touch.clientY }; this._fireMouseEvent('mousedown', touch); } } e.preventDefault(); } _onTouchMove(e) { if (this.viewTouchId === null) return; for (const touch of e.changedTouches) { if (touch.identifier === this.viewTouchId) { const dx = touch.clientX - this.lastTouch.x; const dy = touch.clientY - this.lastTouch.y; this.lastTouch = { x: touch.clientX, y: touch.clientY }; this._fireMouseEvent('mousemove', touch, dx, dy); } } e.preventDefault(); } _onTouchEnd(e) { for (const touch of e.changedTouches) { if (touch.identifier === this.viewTouchId) { this._fireMouseEvent('mouseup', touch); this.viewTouchId = null; this.lastTouch = null; } } e.preventDefault(); } _fireMouseEvent(type, touch, movementX = 0, movementY = 0) { const evt = new MouseEvent(type, { bubbles: true, cancelable: true, clientX: touch.clientX, clientY: touch.clientY, movementX, movementY, buttons: type === 'mouseup' ? 0 : 1 }); this.canvas.dispatchEvent(evt); } }