UNPKG

@ordojs/mobile

Version:

Mobile and PWA support for OrdoJS applications

1 lines 20 kB
{"version":3,"sources":["../src/gestures.ts"],"names":["GestureManager","element","config","event","touch","point","existingPoint","duration","points","startPoint","p","deltaX","deltaY","distance","velocity","direction","point1","point2","startPoint1","startPoint2","startDistance","scale","startAngle","rotation","dx","dy","absX","absY","type","listeners","listener","error","index","newConfig"],"mappings":"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","file":"gestures.mjs","sourcesContent":["import type { GestureConfig, GestureEvent, TouchPoint } from './types';\n\nexport class GestureManager {\n private config: GestureConfig;\n private element: HTMLElement;\n private touchPoints: Map<number, TouchPoint> = new Map();\n private gestureStartTime: number = 0;\n private gestureStartPoints: TouchPoint[] = [];\n private listeners: Map<string, ((event: GestureEvent) => void)[]> = new Map();\n\n constructor(element: HTMLElement, config: Partial<GestureConfig> = {}) {\n this.element = element;\n this.config = {\n enabled: true,\n threshold: 10,\n velocity: 0.3,\n direction: 'both',\n preventDefault: true,\n ...config\n };\n\n this.initialize();\n }\n\n /**\n * Initializes gesture detection\n */\n private initialize(): void {\n if (!this.config.enabled) return;\n\n this.element.addEventListener('touchstart', this.handleTouchStart.bind(this), { passive: false });\n this.element.addEventListener('touchmove', this.handleTouchMove.bind(this), { passive: false });\n this.element.addEventListener('touchend', this.handleTouchEnd.bind(this), { passive: false });\n this.element.addEventListener('touchcancel', this.handleTouchCancel.bind(this), { passive: false });\n }\n\n /**\n * Handles touch start events\n */\n private handleTouchStart(event: TouchEvent): void {\n if (this.config.preventDefault) {\n event.preventDefault();\n }\n\n this.gestureStartTime = Date.now();\n this.gestureStartPoints = [];\n this.touchPoints.clear();\n\n Array.from(event.touches).forEach(touch => {\n const point: TouchPoint = {\n x: touch.clientX,\n y: touch.clientY,\n identifier: touch.identifier,\n timestamp: Date.now()\n };\n this.touchPoints.set(touch.identifier, point);\n this.gestureStartPoints.push({ ...point });\n });\n\n // Detect tap and long press\n if (this.touchPoints.size === 1) {\n this.detectTap();\n this.detectLongPress();\n }\n }\n\n /**\n * Handles touch move events\n */\n private handleTouchMove(event: TouchEvent): void {\n if (this.config.preventDefault) {\n event.preventDefault();\n }\n\n Array.from(event.touches).forEach(touch => {\n const existingPoint = this.touchPoints.get(touch.identifier);\n if (existingPoint) {\n existingPoint.x = touch.clientX;\n existingPoint.y = touch.clientY;\n existingPoint.timestamp = Date.now();\n }\n });\n\n // Detect gestures based on touch count\n if (this.touchPoints.size === 1) {\n this.detectSwipe();\n this.detectPan();\n } else if (this.touchPoints.size === 2) {\n this.detectPinch();\n this.detectRotate();\n }\n }\n\n /**\n * Handles touch end events\n */\n private handleTouchEnd(event: TouchEvent): void {\n if (this.config.preventDefault) {\n event.preventDefault();\n }\n\n const duration = Date.now() - this.gestureStartTime;\n const points = Array.from(this.touchPoints.values());\n\n if (points.length === 1) {\n const point = points[0];\n if (!point) return;\n const startPoint = this.gestureStartPoints.find(p => p.identifier === point.identifier);\n\n if (startPoint) {\n const deltaX = point.x - startPoint.x;\n const deltaY = point.y - startPoint.y;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n const velocity = distance / duration;\n\n // Detect tap\n if (distance < this.config.threshold && duration < 300) {\n this.emitGesture('tap', {\n type: 'tap',\n points: [point],\n deltaX,\n deltaY,\n velocity,\n direction: 'none',\n duration\n });\n }\n\n // Detect swipe\n if (distance > this.config.threshold && velocity > this.config.velocity) {\n const direction = this.getDirection(deltaX, deltaY);\n this.emitGesture('swipe', {\n type: 'swipe',\n points: [point],\n deltaX,\n deltaY,\n velocity,\n direction,\n duration\n });\n }\n }\n }\n\n this.touchPoints.clear();\n this.gestureStartPoints = [];\n }\n\n /**\n * Handles touch cancel events\n */\n private handleTouchCancel(event: TouchEvent): void {\n this.touchPoints.clear();\n this.gestureStartPoints = [];\n }\n\n /**\n * Detects tap gesture\n */\n private detectTap(): void {\n // Tap detection is handled in handleTouchEnd\n }\n\n /**\n * Detects long press gesture\n */\n private detectLongPress(): void {\n setTimeout(() => {\n if (this.touchPoints.size === 1) {\n const point = Array.from(this.touchPoints.values())[0];\n if (!point) return;\n this.emitGesture('longpress', {\n type: 'longpress',\n points: [point],\n deltaX: 0,\n deltaY: 0,\n velocity: 0,\n direction: 'none',\n duration: 500\n });\n }\n }, 500);\n }\n\n /**\n * Detects swipe gesture\n */\n private detectSwipe(): void {\n // Swipe detection is handled in handleTouchEnd\n }\n\n /**\n * Detects pan gesture\n */\n private detectPan(): void {\n const points = Array.from(this.touchPoints.values());\n if (points.length === 1) {\n const point = points[0];\n if (!point) return;\n const startPoint = this.gestureStartPoints.find(p => p.identifier === point.identifier);\n\n if (startPoint) {\n const deltaX = point.x - startPoint.x;\n const deltaY = point.y - startPoint.y;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n if (distance > this.config.threshold) {\n const direction = this.getDirection(deltaX, deltaY);\n this.emitGesture('pan', {\n type: 'pan',\n points: [point],\n deltaX,\n deltaY,\n velocity: distance / (Date.now() - this.gestureStartTime),\n direction,\n duration: Date.now() - this.gestureStartTime\n });\n }\n }\n }\n }\n\n /**\n * Detects pinch gesture\n */\n private detectPinch(): void {\n const points = Array.from(this.touchPoints.values());\n if (points.length === 2) {\n const point1 = points[0];\n const point2 = points[1];\n const startPoint1 = this.gestureStartPoints[0];\n const startPoint2 = this.gestureStartPoints[1];\n\n if (!point1 || !point2 || !startPoint1 || !startPoint2) return;\n\n const startDistance = this.getDistance(startPoint1, startPoint2);\n const currentDistance = this.getDistance(point1, point2);\n const scale = currentDistance / startDistance;\n\n this.emitGesture('pinch', {\n type: 'pinch',\n points,\n deltaX: 0,\n deltaY: 0,\n scale,\n velocity: 0,\n direction: 'none',\n duration: Date.now() - this.gestureStartTime\n });\n }\n }\n\n /**\n * Detects rotate gesture\n */\n private detectRotate(): void {\n const points = Array.from(this.touchPoints.values());\n if (points.length === 2) {\n const point1 = points[0];\n const point2 = points[1];\n const startPoint1 = this.gestureStartPoints[0];\n const startPoint2 = this.gestureStartPoints[1];\n\n if (!point1 || !point2 || !startPoint1 || !startPoint2) return;\n\n const startAngle = this.getAngle(startPoint1, startPoint2);\n const currentAngle = this.getAngle(point1, point2);\n const rotation = currentAngle - startAngle;\n\n this.emitGesture('rotate', {\n type: 'rotate',\n points,\n deltaX: 0,\n deltaY: 0,\n rotation,\n velocity: 0,\n direction: 'none',\n duration: Date.now() - this.gestureStartTime\n });\n }\n }\n\n /**\n * Calculates distance between two points\n */\n private getDistance(point1: TouchPoint, point2: TouchPoint): number {\n const dx = point1.x - point2.x;\n const dy = point1.y - point2.y;\n return Math.sqrt(dx * dx + dy * dy);\n }\n\n /**\n * Calculates angle between two points\n */\n private getAngle(point1: TouchPoint, point2: TouchPoint): number {\n return Math.atan2(point2.y - point1.y, point2.x - point1.x) * 180 / Math.PI;\n }\n\n /**\n * Determines direction based on deltas\n */\n private getDirection(deltaX: number, deltaY: number): 'left' | 'right' | 'up' | 'down' | 'none' {\n const absX = Math.abs(deltaX);\n const absY = Math.abs(deltaY);\n\n if (absX > absY) {\n return deltaX > 0 ? 'right' : 'left';\n } else {\n return deltaY > 0 ? 'down' : 'up';\n }\n }\n\n /**\n * Emits a gesture event\n */\n private emitGesture(type: string, event: GestureEvent): void {\n const listeners = this.listeners.get(type);\n if (listeners) {\n listeners.forEach(listener => {\n try {\n listener(event);\n } catch (error) {\n console.error(`Error in gesture listener for ${type}:`, error);\n }\n });\n }\n }\n\n /**\n * Adds a gesture listener\n */\n on(type: string, listener: (event: GestureEvent) => void): void {\n if (!this.listeners.has(type)) {\n this.listeners.set(type, []);\n }\n this.listeners.get(type)!.push(listener);\n }\n\n /**\n * Removes a gesture listener\n */\n off(type: string, listener: (event: GestureEvent) => void): void {\n const listeners = this.listeners.get(type);\n if (listeners) {\n const index = listeners.indexOf(listener);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n }\n }\n\n /**\n * Updates the configuration\n */\n updateConfig(newConfig: Partial<GestureConfig>): void {\n this.config = { ...this.config, ...newConfig };\n }\n\n /**\n * Gets the current configuration\n */\n getConfig(): GestureConfig {\n return { ...this.config };\n }\n\n /**\n * Destroys the gesture manager\n */\n destroy(): void {\n this.element.removeEventListener('touchstart', this.handleTouchStart.bind(this));\n this.element.removeEventListener('touchmove', this.handleTouchMove.bind(this));\n this.element.removeEventListener('touchend', this.handleTouchEnd.bind(this));\n this.element.removeEventListener('touchcancel', this.handleTouchCancel.bind(this));\n this.listeners.clear();\n this.touchPoints.clear();\n }\n}\n\n// Additional types for gestures\nexport interface GestureOptions {\n threshold?: number;\n velocity?: number;\n direction?: 'horizontal' | 'vertical' | 'both';\n preventDefault?: boolean;\n}\n\nexport interface GestureListener {\n (event: GestureEvent): void;\n}\n"]}