class GestureHandler { constructor(context, transformMatrix, { container }) { this.transformMatrix = transformMatrix; this.containerRect = container; this.panThreshold = 5; this.panStarted = false; // 保存父组件上下文 this.context = context; // 判断是否是小程序环境 this.isMiniProgram = typeof wx !== 'undefined' || typeof uni !== 'undefined'; // 小程序环境下直接使用降级方案 if (this.isMiniProgram) { console.log('小程序环境,使用降级手势处理器'); this.catchEvent = this.createSimpleGestureHandler(); return; } // 非小程序环境尝试使用AnyTouch try { const atOptions = { getPoint: touch => ({ x: touch.clientX - this.containerRect.left, y: touch.clientY - this.containerRect.top }), preventDefault: false }; // 提供兼容小程序的虚拟元素 atOptions.element = { style: {}, addEventListener: () => {}, removeEventListener: () => {}, ownerDocument: { documentElement: { style: {} } } }; // 动态导入AnyTouch避免小程序环境问题 import('any-touch').then(AnyTouch => { this.at = new AnyTouch.default(atOptions); this.setupGestures(); console.log('AnyTouch手势处理器已初始化'); }).catch(e => { console.error('AnyTouch加载失败:', e); this.catchEvent = this.createSimpleGestureHandler(); }); } catch (e) { console.error('AnyTouch初始化失败:', e); this.catchEvent = this.createSimpleGestureHandler(); } } createSimpleGestureHandler() { let isClick = true; let startPoint = null; let startTime = null; let lastPoint = null; return (event) => { // 移除了视图判断 const touches = event.touches || []; if (touches.length === 1) { const getPoint = (t) => ({ x: t.x || (t.clientX - this.containerRect.left), y: t.y || (t.clientY - this.containerRect.top) }); const currentPoint = getPoint(touches[0]); if (!startPoint) { startPoint = currentPoint; startTime = Date.now(); } const dx = currentPoint.x - startPoint.x; const dy = currentPoint.y - startPoint.y; const distance = Math.sqrt(dx * dx + dy * dy); // 区分点击和拖拽 if (isClick && distance < 5 && Date.now() - startTime < 200) { return; } isClick = false; if (lastPoint) { const moveDx = currentPoint.x - lastPoint.x; const moveDy = currentPoint.y - lastPoint.y; this.transformMatrix.tx += moveDx; this.transformMatrix.ty += moveDy; } lastPoint = currentPoint; } else if (touches.length > 1) { this._handlePinch(touches); } // 重置状态 if (event.type === 'touchend' || event.type === 'touchcancel') { isClick = true; startPoint = null; startTime = null; lastPoint = null; } }; } setupGestures() { // 平移手势 this.at.on('pan', (event) => { if (event.type === 'panstart') { this.panStarted = false; } else if (event.type === 'panmove') { console.log('移动') const distance = Math.sqrt(event.deltaX**2 + event.deltaY**2); if (!this.panStarted && distance < this.panThreshold) return; if (!this.panStarted) { this.panStarted = true; } const currentScale = Math.sqrt( this.transformMatrix.a * this.transformMatrix.a + this.transformMatrix.b * this.transformMatrix.b ); const dx = event.deltaX / currentScale; const dy = event.deltaY / currentScale; this.transformMatrix.translate(dx, dy); } else if (event.type === 'panend') { this.panStarted = false; } }); // 缩放手势 this.at.on('pinch', (event) => { if (event.type === 'pinchstart') { this.lastScale = 1; } else if (event.type === 'pinchmove') { const scaleChange = event.scale / this.lastScale; this.lastScale = event.scale; const centerX = event.center.x; const centerY = event.center.y; this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY); } }); } // 公共接口 catchEvent(event) { // 当触摸点数量变化时终止当前手势 if (this.lastTouchCount !== event.touches.length) { this.panStarted = false; this.lastPoints = null; } this.lastTouchCount = event.touches.length; try { if (this.at) { this.at.run(event); } else if (this.catchEvent) { this.catchEvent(event); } } catch (e) { console.error('手势处理错误:', e); } } // 基础平移手势处理 _handlePan(touch) { const getPoint = (t) => ({ x: t.x || (t.clientX - this.containerRect.left), y: t.y || (t.clientY - this.containerRect.top) }); const currentPoint = getPoint(touch); if (this.lastPoint) { const dx = currentPoint.x - this.lastPoint.x; const dy = currentPoint.y - this.lastPoint.y; this.transformMatrix.tx += dx; this.transformMatrix.ty += dy; } this.lastPoint = currentPoint; } // 基础缩放手势处理 // _handlePinch(touches) { // const point1 = touches[0]; // const point2 = touches[1]; // const getPoint = (touch) => ({ // x: touch.x || (touch.clientX - this.containerRect.left), // y: touch.y || (t.clientY - this.containerRect.top) // }); // const currentPoints = [getPoint(point1), getPoint(point2)]; // if (this.lastPoints) { // const currentDistance = Math.sqrt( // Math.pow(currentPoints[1].x - currentPoints[0].x, 2) + // Math.pow(currentPoints[1].y - currentPoints[0].y, 2) // ); // const prevDistance = Math.sqrt( // Math.pow(this.lastPoints[1].x - this.lastPoints[0].x, 2) + // Math.pow(this.lastPoints[1].y - this.lastPoints[0].y, 2) // ); // if (prevDistance > 0 && currentDistance > 0) { // const scaleChange = currentDistance / prevDistance; // const centerX = (currentPoints[0].x + currentPoints[1].x) / 2; // const centerY = (currentPoints[0].y + currentPoints[1].y) / 2; // this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY); // } // } // this.lastPoints = currentPoints; // } _handlePinch(touches) { if (touches.length < 2) return; // 获取当前两点位置 const currentDistance = this.calculateDistance(touches); if (this.lastPinchDistance && currentDistance) { const scaleChange = currentDistance / this.lastPinchDistance; // 计算中心点 const centerX = (touches[0].clientX + touches[1].clientX) / 2; const centerY = (touches[0].clientY + touches[1].clientY) / 2; // 应用缩放 this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY); } this.lastPinchDistance = currentDistance; } calculateDistance(touches) { const dx = touches[0].clientX - touches[1].clientX; const dy = touches[0].clientY - touches[1].clientY; return Math.sqrt(dx * dx + dy * dy); } } export default GestureHandler;