diff --git a/pages/index/gesture-canvas-page.vue b/pages/index/gesture-canvas-page.vue index f40dab5..31f4694 100644 --- a/pages/index/gesture-canvas-page.vue +++ b/pages/index/gesture-canvas-page.vue @@ -25,7 +25,6 @@ - @@ -69,30 +68,35 @@ export default { methods: { // 独立的手势初始化方法 initGestureHandler() { - try { - this.gestureHandler = new GestureHandler(this, this.transformMatrix, { - container: this.containerRect - }); - } catch (e) { - console.error('手势处理器初始化失败:', e); - // 创建降级方案 - this.gestureHandler = { - catchEvent: (event) => { - // 基本手势处理 - const touches = event.touches || []; - if (touches.length > 0) { - const point = touches[0]; - const x = point.clientX - this.containerRect.left; - const y = point.clientY - this.containerRect.top; - - // 简单移动逻辑 - this.transformMatrix.tx = x - 50; - this.transformMatrix.ty = y - 50; - this.updateCanvas(); - } - } - } - } + try { + this.gestureHandler = new GestureHandler(this, this.transformMatrix, { + container: this.containerRect + }); + } catch (e) { + console.error('手势处理器初始化失败:', e); + // 简化降级方案 + this.gestureHandler = { + catchEvent: (event) => { + // 只处理最基本的行为 + if (event.touches.length > 0) { + const firstTouch = event.touches[0]; + const x = firstTouch.clientX - this.containerRect.left; + const y = firstTouch.clientY - this.containerRect.top; + + // 仅更新调试信息显示 + this.gestureStatus = "降级模式: 单指拖动"; + this.touchPoints = event.touches.length; + + // 简单变换 + if (event.type === 'touchmove') { + this.transformMatrix.tx = x; + this.transformMatrix.ty = y; + this.updateCanvas(); + } + } + } + } + } }, async getContainerPosition() { @@ -130,18 +134,35 @@ export default { console.error(`容器位置获取失败,已重试${maxRetries}次`); }, - // 事件处理(完整修复) + // 事件处理 async handleTouchEvent(event) { - // 修复点1:确保处理器就绪的防护代码 + if (!this.gestureHandler || !this.containerRect) { console.warn('手势处理器未就绪,尝试重新初始化...'); await this.getContainerPosition(); this.initGestureHandler(); - + if (event.type === 'touchend' || event.type === 'touchcancel') { + this.lastPoint = null; + this.lastPoints = null; + this.gestureStatus = '结束'; + + // 更新一次画面 + this.updateCanvas(); + return; + } // 重新处理当前事件 if (this.gestureHandler) { return this.handleTouchEvent(event); } + // 如果是简单处理器,使用下面优化的基础处理方法 + if (!this.at) { + // 使用优化后的基础处理方法 + if (correctedEvent.touches.length === 1) { + this.handlePan(correctedEvent.touches[0]); + } else if (correctedEvent.touches.length > 1) { + this.handlePinch(correctedEvent.touches); + } + } return; } @@ -230,14 +251,6 @@ export default { this.updateCanvas(); }, - // 调试输出 - logMatrix() { - console.log('当前变换矩阵:', this.transformMatrix.toArray()); - console.log('容器位置:', this.containerRect); - if (this.$refs.canvasRef) { - this.$refs.canvasRef.drawDebugGrid(); - } - } } }; diff --git a/pages/index/gesture-handler.js b/pages/index/gesture-handler.js index d35e706..c2e267c 100644 --- a/pages/index/gesture-handler.js +++ b/pages/index/gesture-handler.js @@ -4,6 +4,8 @@ class GestureHandler { constructor(context, transformMatrix, { container }) { this.transformMatrix = transformMatrix; this.containerRect = container; + this.panThreshold = 5; // 移动5像素以上才认为是拖动 + this.panStarted = false; // 小程序环境兼容处理 const atOptions = { @@ -49,10 +51,10 @@ class GestureHandler { if (touches.length === 1) { // 单指移动 - this.handlePan(touches[0]); + this._handlePan(touches[0]); } else if (touches.length > 1) { // 双指缩放 - this.handlePinch(touches); + this._handlePinch(touches); } } }; @@ -63,9 +65,23 @@ class GestureHandler { 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 @@ -75,9 +91,12 @@ class GestureHandler { 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; } }); @@ -114,77 +133,92 @@ class GestureHandler { } - catchEvent(event) { - try { - if (this.at) { - this.at.run(event); - } else if (this.handleGesture) { - this.handleGesture.run(event); - } - } catch (e) { - console.error('手势处理错误:', e); - // 降级处理 - const touches = event.touches || []; - if (touches.length > 0) { - this.handlePan(touches[0]); + // 公共接口保持不变 + 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) { - if (this.lastPoint) { - const dx = touch.clientX - this.lastPoint.x; - const dy = touch.clientY - this.lastPoint.y; - - // 根据当前缩放比例修正移动量 - const currentScale = Math.sqrt( - this.transformMatrix.a * this.transformMatrix.a + - this.transformMatrix.b * this.transformMatrix.b - ); - - const correctedDx = dx / currentScale; - const correctedDy = dy / currentScale; - - this.transformMatrix.translate(correctedDx, correctedDy); - } - this.lastPoint = {x: touch.clientX, y: touch.clientY}; + _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) { + _handlePinch(touches) { const point1 = touches[0]; - const point2 = touches[1]; - - if (this.lastPoints) { - // 计算当前距离 - const currentDistance = Math.sqrt( - Math.pow(point2.clientX - point1.clientX, 2) + - Math.pow(point2.clientY - point1.clientY, 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) { - const scaleChange = currentDistance / prevDistance; - - // 计算中心点 - const centerX = (point1.clientX + point2.clientX) / 2 - this.containerRect.left; - const centerY = (point1.clientY + point2.clientY) / 2 - this.containerRect.top; - - this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY); - } - } - - this.lastPoints = [ - {x: point1.clientX, y: point1.clientY}, - {x: point2.clientX, y: point2.clientY} - ]; + 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; } } diff --git a/pages/index/transform-canvas.vue b/pages/index/transform-canvas.vue index 2723c4c..5a281a5 100644 --- a/pages/index/transform-canvas.vue +++ b/pages/index/transform-canvas.vue @@ -52,57 +52,57 @@ export default { }, // 调试网格 - drawDebugGrid() { - if (!this.ctx) return; + // drawDebugGrid() { + // if (!this.ctx) return; - const pixelRatio = uni.getSystemInfoSync().pixelRatio; - const width = this.canvasWidth * pixelRatio; - const height = this.canvasHeight * pixelRatio; + // const pixelRatio = uni.getSystemInfoSync().pixelRatio; + // const width = this.canvasWidth * pixelRatio; + // const height = this.canvasHeight * pixelRatio; - // 保存当前状态 - this.ctx.save(); + // // 保存当前状态 + // this.ctx.save(); - // 重置变换 - this.ctx.setTransform(1, 0, 0, 1, 0, 0); + // // 重置变换 + // this.ctx.setTransform(1, 0, 0, 1, 0, 0); - // 绘制网格 - this.ctx.strokeStyle = 'rgba(200, 200, 200, 0.3)'; - this.ctx.lineWidth = 1; + // // 绘制网格 + // this.ctx.strokeStyle = 'rgba(200, 200, 200, 0.3)'; + // this.ctx.lineWidth = 1; - // 横向线 - for (let y = 0; y <= height; y += 50) { - this.ctx.beginPath(); - this.ctx.moveTo(0, y); - this.ctx.lineTo(width, y); - this.ctx.stroke(); - } + // // 横向线 + // for (let y = 0; y <= height; y += 50) { + // this.ctx.beginPath(); + // this.ctx.moveTo(0, y); + // this.ctx.lineTo(width, y); + // this.ctx.stroke(); + // } - // 纵向线 - for (let x = 0; x <= width; x += 50) { - this.ctx.beginPath(); - this.ctx.moveTo(x, 0); - this.ctx.lineTo(x, height); - this.ctx.stroke(); - } + // // 纵向线 + // for (let x = 0; x <= width; x += 50) { + // this.ctx.beginPath(); + // this.ctx.moveTo(x, 0); + // this.ctx.lineTo(x, height); + // this.ctx.stroke(); + // } - // 绘制坐标轴 - this.ctx.strokeStyle = '#ff0000'; - this.ctx.lineWidth = 2; - this.ctx.beginPath(); - this.ctx.moveTo(0, 0); - this.ctx.lineTo(width, 0); - this.ctx.stroke(); + // // 绘制坐标轴 + // this.ctx.strokeStyle = '#ff0000'; + // this.ctx.lineWidth = 2; + // this.ctx.beginPath(); + // this.ctx.moveTo(0, 0); + // this.ctx.lineTo(width, 0); + // this.ctx.stroke(); - this.ctx.beginPath(); - this.ctx.moveTo(0, 0); - this.ctx.lineTo(0, height); - this.ctx.stroke(); + // this.ctx.beginPath(); + // this.ctx.moveTo(0, 0); + // this.ctx.lineTo(0, height); + // this.ctx.stroke(); - // 恢复之前的状态 - this.ctx.restore(); + // // 恢复之前的状态 + // this.ctx.restore(); - this.ctx.draw(); - }, + // this.ctx.draw(); + // }, // 绘制主内容 draw() { diff --git a/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-canvas-page.js.map b/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-canvas-page.js.map index aa8200a..7c78ca3 100644 --- a/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-canvas-page.js.map +++ b/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-canvas-page.js.map @@ -1 +1 @@ -{"version":3,"file":"gesture-canvas-page.js","sources":["pages/index/gesture-canvas-page.vue?type=page"],"sourcesContent":["import MiniProgramPage from '/Users/sunmeng/Desktop/wx/canvas/pages/index/gesture-canvas-page.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"} \ No newline at end of file +{"version":3,"file":"gesture-canvas-page.js","sources":["pages/index/gesture-canvas-page.vue?type=page"],"sourcesContent":["import MiniProgramPage from '/Users/sunmeng/Desktop/wx/canvas/pages/index/gesture-canvas-page.vue'\nwx.createPage(MiniProgramPage)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,WAAW,eAAe;"} \ No newline at end of file diff --git a/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-handler.js.map b/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-handler.js.map index 39c7d67..30e4872 100644 --- a/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-handler.js.map +++ b/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/gesture-handler.js.map @@ -1 +1 @@ -{"version":3,"file":"gesture-handler.js","sources":["pages/index/gesture-handler.js"],"sourcesContent":["import AnyTouch from 'any-touch'\n\nclass GestureHandler {\n constructor(context, transformMatrix, { container }) {\n this.transformMatrix = transformMatrix;\n this.containerRect = container;\n \n // 小程序环境兼容处理\n const atOptions = {\n getPoint: touch => ({\n x: touch.clientX - this.containerRect.left,\n y: touch.clientY - this.containerRect.top\n }),\n preventDefault: false\n };\n \n // 小程序特化处理 - 跳过DOM相关操作\n if (typeof window === 'undefined' || typeof HTMLElement === 'undefined') {\n // 小程序环境下不需要设置DOM属性\n atOptions._element = { \n style: {},\n addEventListener: () => {},\n removeEventListener: () => {}\n };\n }\n \n try {\n this.at = new AnyTouch(atOptions);\n } catch (e) {\n console.error('AnyTouch初始化失败:', e);\n // 降级方案:在小程序环境实现基本手势\n this.handleGesture = this.createSimpleGestureHandler();\n }\n \n if (this.at) {\n this.setupGestures();\n console.log('AnyTouch手势处理器已初始化');\n } else {\n console.warn('使用简化手势处理器');\n }\n }\n \n // 创建小程序专用的简化手势处理器\n createSimpleGestureHandler() {\n return {\n run: (event) => {\n // 小程序环境下的基本手势实现\n const touches = event.touches || [];\n \n if (touches.length === 1) {\n // 单指移动\n this.handlePan(touches[0]);\n } else if (touches.length > 1) {\n // 双指缩放\n this.handlePinch(touches);\n }\n }\n };\n }\n \n setupGestures() {\n // 平移手势 - 修复版本\n this.at.on('pan', (event) => {\n if (event.type === 'panstart') {\n console.log('panstart', event);\n }\n else if (event.type === 'panmove') {\n // 关键修复:基于当前缩放比例修正移动量\n const currentScale = Math.sqrt(\n this.transformMatrix.a * this.transformMatrix.a +\n this.transformMatrix.b * this.transformMatrix.b\n );\n \n // 逆缩放移动量\n const dx = event.deltaX / currentScale;\n const dy = event.deltaY / currentScale;\n \n console.log(`平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`);\n \n this.transformMatrix.translate(dx, dy);\n }\n });\n \n // 缩放手势 - 修复版本\n this.at.on('pinch', (event) => {\n if (event.type === 'pinchstart') {\n this.lastScale = 1;\n }\n else if (event.type === 'pinchmove') {\n // 计算缩放变化量\n const scaleChange = event.scale / this.lastScale;\n this.lastScale = event.scale;\n \n // 使用两指中心点\n const centerX = event.center.x;\n const centerY = event.center.y;\n \n console.log(`缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`);\n \n // 应用缩放\n this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);\n }\n });\n \n // 点击手势\n this.at.on('tap', (event) => {\n console.log('点击事件', event);\n });\n \n // 长按手势\n this.at.on('press', (event) => {\n console.log('长按事件', event);\n });\n }\n \n \n catchEvent(event) {\n try {\n if (this.at) {\n this.at.run(event);\n } else if (this.handleGesture) {\n this.handleGesture.run(event);\n }\n } catch (e) {\n console.error('手势处理错误:', e);\n // 降级处理\n const touches = event.touches || [];\n if (touches.length > 0) {\n this.handlePan(touches[0]);\n }\n }\n }\n \n // 基础平移手势处理\n handlePan(touch) {\n if (this.lastPoint) {\n const dx = touch.clientX - this.lastPoint.x;\n const dy = touch.clientY - this.lastPoint.y;\n \n // 根据当前缩放比例修正移动量\n const currentScale = Math.sqrt(\n this.transformMatrix.a * this.transformMatrix.a +\n this.transformMatrix.b * this.transformMatrix.b\n );\n \n const correctedDx = dx / currentScale;\n const correctedDy = dy / currentScale;\n \n this.transformMatrix.translate(correctedDx, correctedDy);\n }\n this.lastPoint = {x: touch.clientX, y: touch.clientY};\n }\n \n // 基础缩放手势处理\n handlePinch(touches) {\n const point1 = touches[0];\n const point2 = touches[1];\n \n if (this.lastPoints) {\n // 计算当前距离\n const currentDistance = Math.sqrt(\n Math.pow(point2.clientX - point1.clientX, 2) + \n Math.pow(point2.clientY - point1.clientY, 2)\n );\n \n // 上次距离\n const prevDistance = Math.sqrt(\n Math.pow(this.lastPoints[1].x - this.lastPoints[0].x, 2) + \n Math.pow(this.lastPoints[1].y - this.lastPoints[0].y, 2)\n );\n \n // 缩放比例\n if (prevDistance > 0) {\n const scaleChange = currentDistance / prevDistance;\n \n // 计算中心点\n const centerX = (point1.clientX + point2.clientX) / 2 - this.containerRect.left;\n const centerY = (point1.clientY + point2.clientY) / 2 - this.containerRect.top;\n \n this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);\n }\n }\n \n this.lastPoints = [\n {x: point1.clientX, y: point1.clientY},\n {x: point2.clientX, y: point2.clientY}\n ];\n }\n}\n\nexport default GestureHandler;"],"names":["AnyTouch","uni"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"gesture-handler.js","sources":["pages/index/gesture-handler.js"],"sourcesContent":["import AnyTouch from 'any-touch'\n\nclass GestureHandler {\n constructor(context, transformMatrix, { container }) {\n this.transformMatrix = transformMatrix;\n this.containerRect = container;\n\t\tthis.panThreshold = 5; // 移动5像素以上才认为是拖动\n\t\tthis.panStarted = false;\n \n // 小程序环境兼容处理\n const atOptions = {\n getPoint: touch => ({\n x: touch.clientX - this.containerRect.left,\n y: touch.clientY - this.containerRect.top\n }),\n preventDefault: false\n };\n \n // 小程序特化处理 - 跳过DOM相关操作\n if (typeof window === 'undefined' || typeof HTMLElement === 'undefined') {\n // 小程序环境下不需要设置DOM属性\n atOptions._element = { \n style: {},\n addEventListener: () => {},\n removeEventListener: () => {}\n };\n }\n \n try {\n this.at = new AnyTouch(atOptions);\n } catch (e) {\n console.error('AnyTouch初始化失败:', e);\n // 降级方案:在小程序环境实现基本手势\n this.handleGesture = this.createSimpleGestureHandler();\n }\n \n if (this.at) {\n this.setupGestures();\n console.log('AnyTouch手势处理器已初始化');\n } else {\n console.warn('使用简化手势处理器');\n }\n }\n \n // 创建小程序专用的简化手势处理器\n createSimpleGestureHandler() {\n return {\n run: (event) => {\n // 小程序环境下的基本手势实现\n const touches = event.touches || [];\n \n if (touches.length === 1) {\n // 单指移动\n this._handlePan(touches[0]);\n } else if (touches.length > 1) {\n // 双指缩放\n this._handlePinch(touches);\n }\n }\n };\n }\n \n setupGestures() {\n // 平移手势 - 修复版本\n this.at.on('pan', (event) => {\n if (event.type === 'panstart') {\n console.log('panstart', event);\n\t\t\t\t// 重置移动开始状态\n\t\t\t\tthis.panStarted = false;\n }\n else if (event.type === 'panmove') {\n\t\t\t\t// 检查是否超过阈值\n\t\t\t\tconst distance = Math.sqrt(event.deltaX**2 + event.deltaY**2);\n\t\t\t\t\n\t\t\t\tif (!this.panStarted && distance < this.panThreshold) {\n\t\t\t\t\treturn; // 小于阈值不处理\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!this.panStarted) {\n\t\t\t\t\tconsole.log('拖动手势开始');\n\t\t\t\t\tthis.panStarted = true;\n\t\t\t\t}\n\t\t\t\t\n // 基于当前缩放比例修正移动量\n const currentScale = Math.sqrt(\n this.transformMatrix.a * this.transformMatrix.a +\n this.transformMatrix.b * this.transformMatrix.b\n );\n \n // 逆缩放移动量\n const dx = event.deltaX / currentScale;\n const dy = event.deltaY / currentScale;\n \n\t\t\t\t\n console.log(`平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`);\n \n this.transformMatrix.translate(dx, dy);\n } else if (event.type === 'panend') {\n this.panStarted = false;\n }\n });\n \n // 缩放手势 - 修复版本\n this.at.on('pinch', (event) => {\n if (event.type === 'pinchstart') {\n this.lastScale = 1;\n }\n else if (event.type === 'pinchmove') {\n // 计算缩放变化量\n const scaleChange = event.scale / this.lastScale;\n this.lastScale = event.scale;\n \n // 使用两指中心点\n const centerX = event.center.x;\n const centerY = event.center.y;\n \n console.log(`缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`);\n \n // 应用缩放\n this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);\n }\n });\n \n // 点击手势\n this.at.on('tap', (event) => {\n console.log('点击事件', event);\n });\n \n // 长按手势\n this.at.on('press', (event) => {\n console.log('长按事件', event);\n });\n }\n \n \n // 公共接口保持不变\n catchEvent(event) {\n try {\n if (this.at) {\n this.at.run(event);\n } else {\n // 内部处理降级方案\n const touches = event.touches || [];\n const eventType = event.type;\n \n // 在事件开始时重置状态\n if (eventType === 'touchstart') {\n this.lastPoint = null;\n this.lastPoints = null;\n this.lastDistance = null;\n }\n \n // 处理不同数量的手指\n if (touches.length === 1) {\n this._handlePan(touches[0]);\n } else if (touches.length > 1) {\n this._handlePinch(touches);\n }\n }\n } catch (e) {\n console.error('手势处理错误:', e);\n }\n }\n // 基础平移手势处理\n _handlePan(touch) {\n const pointX = touch.x || (touch.clientX - this.containerRect.left);\n\t\tconst pointY = touch.y || (touch.clientY - this.containerRect.top);\n\t\n\t\tif (this.lastPoint) {\n\t\t\t// 基于容器坐标系的增量计算\n\t\t\tconst dx = pointX - this.lastPoint.x;\n\t\t\tconst dy = pointY - this.lastPoint.y;\n\t\t\t\n\t\t\t// 使用真实增量,不需要缩放修正\n\t\t\tthis.transformMatrix.translate(dx, dy);\n\t\t}\n\t\t\n\t\t// 存储当前点 (容器坐标系)\n\t\tthis.lastPoint = {x: pointX, y: pointY};\n }\n \n // 基础缩放手势处理\n _handlePinch(touches) {\n const point1 = touches[0];\n\t\tconst point2 = touches[1];\n\t\t\n\t\t// 获取容器坐标系坐标\n\t\tconst getPoint = (touch) => ({\n\t\t\tx: touch.x || (touch.clientX - this.containerRect.left),\n\t\t\ty: touch.y || (touch.clientY - this.containerRect.top)\n\t\t});\n\t\t\n\t\tconst currentPoints = [getPoint(point1), getPoint(point2)];\n\t\t\n\t\tif (this.lastPoints) {\n\t\t\t// 计算当前距离 (容器坐标系)\n\t\t\tconst currentDistance = Math.sqrt(\n\t\t\t\tMath.pow(currentPoints[1].x - currentPoints[0].x, 2) + \n\t\t\t\tMath.pow(currentPoints[1].y - currentPoints[0].y, 2)\n\t\t\t);\n\t\t\t\n\t\t\t// 上次距离 (容器坐标系)\n\t\t\tconst prevDistance = Math.sqrt(\n\t\t\t\tMath.pow(this.lastPoints[1].x - this.lastPoints[0].x, 2) + \n\t\t\t\tMath.pow(this.lastPoints[1].y - this.lastPoints[0].y, 2)\n\t\t\t);\n\t\t\t\n\t\t\t// 缩放比例\n\t\t\tif (prevDistance > 0 && currentDistance > 0) {\n\t\t\t\tconst scaleChange = currentDistance / prevDistance;\n\t\t\t\t\n\t\t\t\t// 计算中心点 (容器坐标系)\n\t\t\t\tconst centerX = (currentPoints[0].x + currentPoints[1].x) / 2;\n\t\t\t\tconst centerY = (currentPoints[0].y + currentPoints[1].y) / 2;\n\t\t\t\t\n\t\t\t\tthis.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// 存储当前点\n\t\tthis.lastPoints = currentPoints;\n }\n}\n\nexport default GestureHandler;"],"names":["AnyTouch","uni"],"mappings":"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"} \ No newline at end of file diff --git a/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/transform-canvas.js.map b/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/transform-canvas.js.map index 45ceeef..3a41822 100644 --- a/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/transform-canvas.js.map +++ b/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/transform-canvas.js.map @@ -1 +1 @@ -{"version":3,"file":"transform-canvas.js","sources":["/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue?type=component"],"sourcesContent":["import Component from '/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue'\nwx.createComponent(Component)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,gBAAgB,SAAS;"} \ No newline at end of file +{"version":3,"file":"transform-canvas.js","sources":["/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue?type=component"],"sourcesContent":["import Component from '/Users/sunmeng/Desktop/wx/canvas/pages/index/transform-canvas.vue'\nwx.createComponent(Component)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,gBAAgB,SAAS;"} \ No newline at end of file diff --git a/unpackage/dist/dev/mp-weixin/common/vendor.js b/unpackage/dist/dev/mp-weixin/common/vendor.js index 1d49d33..def1e28 100644 --- a/unpackage/dist/dev/mp-weixin/common/vendor.js +++ b/unpackage/dist/dev/mp-weixin/common/vendor.js @@ -6882,7 +6882,7 @@ function initOnError() { function initRuntimeSocketService() { const hosts = "127.0.0.1,172.10.0.205"; const port = "8090"; - const id = "mp-weixin_j4oiF-"; + const id = "mp-weixin_aMdMwA"; const lazy = typeof swan !== "undefined"; let restoreError = lazy ? () => { } : initOnError(); diff --git a/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.js b/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.js index 91dea19..af6efec 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.js +++ b/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.js @@ -35,17 +35,20 @@ const _sfc_main = { container: this.containerRect }); } catch (e) { - common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:77", "手势处理器初始化失败:", e); + common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:76", "手势处理器初始化失败:", e); this.gestureHandler = { catchEvent: (event) => { - const touches = event.touches || []; - if (touches.length > 0) { - const point = touches[0]; - const x = point.clientX - this.containerRect.left; - const y = point.clientY - this.containerRect.top; - this.transformMatrix.tx = x - 50; - this.transformMatrix.ty = y - 50; - this.updateCanvas(); + if (event.touches.length > 0) { + const firstTouch = event.touches[0]; + const x = firstTouch.clientX - this.containerRect.left; + const y = firstTouch.clientY - this.containerRect.top; + this.gestureStatus = "降级模式: 单指拖动"; + this.touchPoints = event.touches.length; + if (event.type === "touchmove") { + this.transformMatrix.tx = x; + this.transformMatrix.ty = y; + this.updateCanvas(); + } } } }; @@ -69,26 +72,40 @@ const _sfc_main = { width: rect.width, height: rect.height }; - common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:119", "成功获取容器位置:", this.containerRect); + common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:123", "成功获取容器位置:", this.containerRect); return; } } catch (e) { - common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:123", "获取容器位置失败:", e); + common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:127", "获取容器位置失败:", e); } await new Promise((r) => setTimeout(r, 100)); retryCount++; } - common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:131", `容器位置获取失败,已重试${maxRetries}次`); + common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:135", `容器位置获取失败,已重试${maxRetries}次`); }, - // 事件处理(完整修复) + // 事件处理 async handleTouchEvent(event) { if (!this.gestureHandler || !this.containerRect) { - common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:137", "手势处理器未就绪,尝试重新初始化..."); + common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:141", "手势处理器未就绪,尝试重新初始化..."); await this.getContainerPosition(); this.initGestureHandler(); + if (event.type === "touchend" || event.type === "touchcancel") { + this.lastPoint = null; + this.lastPoints = null; + this.gestureStatus = "结束"; + this.updateCanvas(); + return; + } if (this.gestureHandler) { return this.handleTouchEvent(event); } + if (!this.at) { + if (correctedEvent.touches.length === 1) { + this.handlePan(correctedEvent.touches[0]); + } else if (correctedEvent.touches.length > 1) { + this.handlePinch(correctedEvent.touches); + } + } return; } const currentTime = Date.now(); @@ -96,7 +113,7 @@ const _sfc_main = { const correctedTouches = Array.from(event.touches).map((touch) => { const x = touch.clientX - this.containerRect.left; const y = touch.clientY - this.containerRect.top; - common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:160", `原始坐标: (${touch.clientX}, ${touch.clientY}) 修正后: (${x}, ${y})`); + common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:181", `原始坐标: (${touch.clientX}, ${touch.clientY}) 修正后: (${x}, ${y})`); return { ...touch, x, @@ -149,14 +166,6 @@ const _sfc_main = { zoomOut() { this.transformMatrix.scale(0.8, 0.8, this.canvasWidth / 2, this.canvasHeight / 2); this.updateCanvas(); - }, - // 调试输出 - logMatrix() { - common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:235", "当前变换矩阵:", this.transformMatrix.toArray()); - common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:236", "容器位置:", this.containerRect); - if (this.$refs.canvasRef) { - this.$refs.canvasRef.drawDebugGrid(); - } } } }; @@ -183,8 +192,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { k: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)), l: common_vendor.o((...args) => $options.resetCanvas && $options.resetCanvas(...args)), m: common_vendor.o((...args) => $options.zoomIn && $options.zoomIn(...args)), - n: common_vendor.o((...args) => $options.zoomOut && $options.zoomOut(...args)), - o: common_vendor.o((...args) => $options.logMatrix && $options.logMatrix(...args)) + n: common_vendor.o((...args) => $options.zoomOut && $options.zoomOut(...args)) }; } const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-2e633000"]]); diff --git a/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.wxml b/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.wxml index 6d4fa6d..f0ddf49 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.wxml +++ b/unpackage/dist/dev/mp-weixin/pages/index/gesture-canvas-page.wxml @@ -1 +1 @@ -缩放: {{a}} | X: {{b}} | Y: {{c}}手势: {{d}}触点: {{e}} \ No newline at end of file +缩放: {{a}} | X: {{b}} | Y: {{c}}手势: {{d}}触点: {{e}} \ No newline at end of file diff --git a/unpackage/dist/dev/mp-weixin/pages/index/gesture-handler.js b/unpackage/dist/dev/mp-weixin/pages/index/gesture-handler.js index c5990e3..1615762 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/gesture-handler.js +++ b/unpackage/dist/dev/mp-weixin/pages/index/gesture-handler.js @@ -4,6 +4,8 @@ class GestureHandler { constructor(context, transformMatrix, { container }) { this.transformMatrix = transformMatrix; this.containerRect = container; + this.panThreshold = 5; + this.panStarted = false; const atOptions = { getPoint: (touch) => ({ x: touch.clientX - this.containerRect.left, @@ -23,14 +25,14 @@ class GestureHandler { try { this.at = new common_vendor.i(atOptions); } catch (e) { - common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:30", "AnyTouch初始化失败:", e); + common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:32", "AnyTouch初始化失败:", e); this.handleGesture = this.createSimpleGestureHandler(); } if (this.at) { this.setupGestures(); - common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:37", "AnyTouch手势处理器已初始化"); + common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:39", "AnyTouch手势处理器已初始化"); } else { - common_vendor.index.__f__("warn", "at pages/index/gesture-handler.js:39", "使用简化手势处理器"); + common_vendor.index.__f__("warn", "at pages/index/gesture-handler.js:41", "使用简化手势处理器"); } } // 创建小程序专用的简化手势处理器 @@ -39,9 +41,9 @@ class GestureHandler { run: (event) => { const touches = event.touches || []; if (touches.length === 1) { - this.handlePan(touches[0]); + this._handlePan(touches[0]); } else if (touches.length > 1) { - this.handlePinch(touches); + this._handlePinch(touches); } } }; @@ -49,15 +51,26 @@ class GestureHandler { setupGestures() { this.at.on("pan", (event) => { if (event.type === "panstart") { - common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:65", "panstart", event); + common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:67", "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) { + common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:80", "拖动手势开始"); + 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; - common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:78", `平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`); + common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:95", `平移: 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) => { @@ -68,68 +81,75 @@ class GestureHandler { this.lastScale = event.scale; const centerX = event.center.x; const centerY = event.center.y; - common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:98", `缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`); + common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:117", `缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`); this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY); } }); this.at.on("tap", (event) => { - common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:107", "点击事件", event); + common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:126", "点击事件", event); }); this.at.on("press", (event) => { - common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:112", "长按事件", event); + common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:131", "长按事件", event); }); } + // 公共接口保持不变 catchEvent(event) { try { if (this.at) { this.at.run(event); - } else if (this.handleGesture) { - this.handleGesture.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) { - common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:125", "手势处理错误:", e); - const touches = event.touches || []; - if (touches.length > 0) { - this.handlePan(touches[0]); - } + common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:161", "手势处理错误:", e); } } // 基础平移手势处理 - handlePan(touch) { + _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 = touch.clientX - this.lastPoint.x; - const dy = touch.clientY - this.lastPoint.y; - const currentScale = Math.sqrt( - this.transformMatrix.a * this.transformMatrix.a + this.transformMatrix.b * this.transformMatrix.b - ); - const correctedDx = dx / currentScale; - const correctedDy = dy / currentScale; - this.transformMatrix.translate(correctedDx, correctedDy); + const dx = pointX - this.lastPoint.x; + const dy = pointY - this.lastPoint.y; + this.transformMatrix.translate(dx, dy); } - this.lastPoint = { x: touch.clientX, y: touch.clientY }; + this.lastPoint = { x: pointX, y: pointY }; } // 基础缩放手势处理 - handlePinch(touches) { + _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(point2.clientX - point1.clientX, 2) + Math.pow(point2.clientY - point1.clientY, 2) + 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) { + if (prevDistance > 0 && currentDistance > 0) { const scaleChange = currentDistance / prevDistance; - const centerX = (point1.clientX + point2.clientX) / 2 - this.containerRect.left; - const centerY = (point1.clientY + point2.clientY) / 2 - this.containerRect.top; + 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 = [ - { x: point1.clientX, y: point1.clientY }, - { x: point2.clientX, y: point2.clientY } - ]; + this.lastPoints = currentPoints; } } exports.GestureHandler = GestureHandler; diff --git a/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js b/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js index 52b6961..778f5c0 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js +++ b/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js @@ -38,41 +38,47 @@ const _sfc_main = { ); }, // 调试网格 - drawDebugGrid() { - if (!this.ctx) - return; - const pixelRatio = common_vendor.index.getSystemInfoSync().pixelRatio; - const width = this.canvasWidth * pixelRatio; - const height = this.canvasHeight * pixelRatio; - this.ctx.save(); - this.ctx.setTransform(1, 0, 0, 1, 0, 0); - this.ctx.strokeStyle = "rgba(200, 200, 200, 0.3)"; - this.ctx.lineWidth = 1; - for (let y = 0; y <= height; y += 50) { - this.ctx.beginPath(); - this.ctx.moveTo(0, y); - this.ctx.lineTo(width, y); - this.ctx.stroke(); - } - for (let x = 0; x <= width; x += 50) { - this.ctx.beginPath(); - this.ctx.moveTo(x, 0); - this.ctx.lineTo(x, height); - this.ctx.stroke(); - } - this.ctx.strokeStyle = "#ff0000"; - this.ctx.lineWidth = 2; - this.ctx.beginPath(); - this.ctx.moveTo(0, 0); - this.ctx.lineTo(width, 0); - this.ctx.stroke(); - this.ctx.beginPath(); - this.ctx.moveTo(0, 0); - this.ctx.lineTo(0, height); - this.ctx.stroke(); - this.ctx.restore(); - this.ctx.draw(); - }, + // drawDebugGrid() { + // if (!this.ctx) return; + // const pixelRatio = uni.getSystemInfoSync().pixelRatio; + // const width = this.canvasWidth * pixelRatio; + // const height = this.canvasHeight * pixelRatio; + // // 保存当前状态 + // this.ctx.save(); + // // 重置变换 + // this.ctx.setTransform(1, 0, 0, 1, 0, 0); + // // 绘制网格 + // this.ctx.strokeStyle = 'rgba(200, 200, 200, 0.3)'; + // this.ctx.lineWidth = 1; + // // 横向线 + // for (let y = 0; y <= height; y += 50) { + // this.ctx.beginPath(); + // this.ctx.moveTo(0, y); + // this.ctx.lineTo(width, y); + // this.ctx.stroke(); + // } + // // 纵向线 + // for (let x = 0; x <= width; x += 50) { + // this.ctx.beginPath(); + // this.ctx.moveTo(x, 0); + // this.ctx.lineTo(x, height); + // this.ctx.stroke(); + // } + // // 绘制坐标轴 + // this.ctx.strokeStyle = '#ff0000'; + // this.ctx.lineWidth = 2; + // this.ctx.beginPath(); + // this.ctx.moveTo(0, 0); + // this.ctx.lineTo(width, 0); + // this.ctx.stroke(); + // this.ctx.beginPath(); + // this.ctx.moveTo(0, 0); + // this.ctx.lineTo(0, height); + // this.ctx.stroke(); + // // 恢复之前的状态 + // this.ctx.restore(); + // this.ctx.draw(); + // }, // 绘制主内容 draw() { if (!this.ctx) {