import AnyTouch from 'any-touch' class GestureHandler { constructor(context, transformMatrix, { container }) { this.transformMatrix = transformMatrix; this.containerRect = container; this.panThreshold = 5; // 移动5像素以上才认为是拖动 this.panStarted = false; // 小程序环境兼容处理 const atOptions = { getPoint: touch => ({ x: touch.clientX - this.containerRect.left, y: touch.clientY - this.containerRect.top }), preventDefault: false }; // 小程序特化处理 - 跳过DOM相关操作 if (typeof window === 'undefined' || typeof HTMLElement === 'undefined') { // 小程序环境下不需要设置DOM属性 atOptions._element = { style: {}, addEventListener: () => {}, removeEventListener: () => {} }; } try { this.at = new AnyTouch(atOptions); } catch (e) { console.error('AnyTouch初始化失败:', e); // 降级方案:在小程序环境实现基本手势 this.handleGesture = this.createSimpleGestureHandler(); } if (this.at) { this.setupGestures(); console.log('AnyTouch手势处理器已初始化'); } else { console.warn('使用简化手势处理器'); } } // 创建小程序专用的简化手势处理器 createSimpleGestureHandler() { return { run: (event) => { // 小程序环境下的基本手势实现 const touches = event.touches || []; if (touches.length === 1) { // 单指移动 this._handlePan(touches[0]); } else if (touches.length > 1) { // 双指缩放 this._handlePinch(touches); } } }; } setupGestures() { // 平移手势 - 修复版本 this.at.on('pan', (event) => { if (event.type === 'panstart') { console.log('panstart', event); // 重置移动开始状态 this.panStarted = false; } else if (event.type === 'panmove') { // 检查是否超过阈值 const distance = Math.sqrt(event.deltaX**2 + event.deltaY**2); if (!this.panStarted && distance < this.panThreshold) { return; // 小于阈值不处理 } if (!this.panStarted) { console.log('拖动手势开始'); 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; console.log(`平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`); 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; console.log(`缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`); // 应用缩放 this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY); } }); // 点击手势 this.at.on('tap', (event) => { console.log('点击事件', event); }); // 长按手势 this.at.on('press', (event) => { console.log('长按事件', event); }); } // 公共接口保持不变 catchEvent(event) { try { if (this.at) { this.at.run(event); } else { // 内部处理降级方案 const touches = event.touches || []; const eventType = event.type; // 在事件开始时重置状态 if (eventType === 'touchstart') { this.lastPoint = null; this.lastPoints = null; this.lastDistance = null; } // 处理不同数量的手指 if (touches.length === 1) { this._handlePan(touches[0]); } else if (touches.length > 1) { this._handlePinch(touches); } } } catch (e) { console.error('手势处理错误:', e); } } // 基础平移手势处理 _handlePan(touch) { const pointX = touch.x || (touch.clientX - this.containerRect.left); const pointY = touch.y || (touch.clientY - this.containerRect.top); if (this.lastPoint) { // 基于容器坐标系的增量计算 const dx = pointX - this.lastPoint.x; const dy = pointY - this.lastPoint.y; // 使用真实增量,不需要缩放修正 this.transformMatrix.translate(dx, dy); } // 存储当前点 (容器坐标系) this.lastPoint = {x: pointX, y: pointY}; } // 基础缩放手势处理 _handlePinch(touches) { const point1 = touches[0]; const point2 = touches[1]; // 获取容器坐标系坐标 const getPoint = (touch) => ({ x: touch.x || (touch.clientX - this.containerRect.left), y: touch.y || (touch.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; } } export default GestureHandler;