UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

121 lines (120 loc) 3.67 kB
import { Vec2 } from "../../../core/math/vec2.js"; import { InputSource } from "../input.js"; import { movementState } from "../utils.js"; const tmpVa = new Vec2(); class MultiTouchSource extends InputSource { _movementState = movementState(); _pointerEvents = /* @__PURE__ */ new Map(); _pointerPos = new Vec2(); _pinchDist = -1; constructor() { super({ touch: [0, 0], count: [0], pinch: [0] }); this._onPointerDown = this._onPointerDown.bind(this); this._onPointerMove = this._onPointerMove.bind(this); this._onPointerUp = this._onPointerUp.bind(this); this._onContextMenu = this._onContextMenu.bind(this); } _onPointerDown(event) { const { pointerId, pointerType } = event; this._movementState.down(event); if (pointerType !== "touch") { return; } this._element?.setPointerCapture(pointerId); this._pointerEvents.set(pointerId, event); this.deltas.count.append([1]); if (this._pointerEvents.size > 1) { this._getMidPoint(this._pointerPos); this._pinchDist = this._getPinchDist(); } } _onPointerMove(event) { const { pointerType, target, pointerId } = event; const [movementX, movementY] = this._movementState.move(event); if (pointerType !== "touch") { return; } if (target !== this._element) { return; } if (this._pointerEvents.size === 0) { return; } this._pointerEvents.set(pointerId, event); if (this._pointerEvents.size > 1) { const mid = this._getMidPoint(tmpVa); this.deltas.touch.append([mid.x - this._pointerPos.x, mid.y - this._pointerPos.y]); this._pointerPos.copy(mid); const pinchDist = this._getPinchDist(); if (this._pinchDist > 0) { this.deltas.pinch.append([this._pinchDist - pinchDist]); } this._pinchDist = pinchDist; } else { this.deltas.touch.append([movementX, movementY]); } } _onPointerUp(event) { const { pointerType, pointerId } = event; this._movementState.up(event); if (pointerType !== "touch") { return; } this._element?.releasePointerCapture(pointerId); this._pointerEvents.delete(pointerId); this.deltas.count.append([-1]); if (this._pointerEvents.size < 2) { this._pinchDist = -1; } this._pointerPos.set(0, 0); } _onContextMenu(event) { event.preventDefault(); } _getMidPoint(out) { if (this._pointerEvents.size < 2) { return out.set(0, 0); } const [a, b] = this._pointerEvents.values(); const dx = a.clientX - b.clientX; const dy = a.clientY - b.clientY; return out.set(b.clientX + dx * 0.5, b.clientY + dy * 0.5); } _getPinchDist() { if (this._pointerEvents.size < 2) { return 0; } const [a, b] = this._pointerEvents.values(); const dx = a.clientX - b.clientX; const dy = a.clientY - b.clientY; return Math.sqrt(dx * dx + dy * dy); } attach(element) { super.attach(element); this._element = element; this._element.addEventListener("pointerdown", this._onPointerDown); this._element.addEventListener("pointermove", this._onPointerMove); this._element.addEventListener("pointerup", this._onPointerUp); this._element.addEventListener("pointercancel", this._onPointerUp); this._element.addEventListener("contextmenu", this._onContextMenu); } detach() { if (!this._element) { return; } this._element.removeEventListener("pointerdown", this._onPointerDown); this._element.removeEventListener("pointermove", this._onPointerMove); this._element.removeEventListener("pointerup", this._onPointerUp); this._element.removeEventListener("pointercancel", this._onPointerUp); this._element.removeEventListener("contextmenu", this._onContextMenu); this._pointerEvents.clear(); super.detach(); } } export { MultiTouchSource };