diff --git a/pages/index/gesture-canvas-page.vue b/pages/index/gesture-canvas-page.vue index f6669a8..206fb7a 100644 --- a/pages/index/gesture-canvas-page.vue +++ b/pages/index/gesture-canvas-page.vue @@ -42,8 +42,8 @@ export default { data() { return { - canvasWidth: 300, - canvasHeight: 300, + canvasWidth: 800, + canvasHeight: 600, transformMatrix: new TransformMatrix(), gestureHandler: null, containerRect: null, @@ -151,10 +151,9 @@ export default { this.updateCanvas(); return; } - // 重新处理当前事件 - if (this.gestureHandler) { - return this.handleTouchEvent(event); - } + // 直接传递原始事件,手势处理器会处理坐标转换 + this.gestureHandler.catchEvent(event); + // 如果是简单处理器,使用下面优化的基础处理方法 if (!this.at) { // 使用优化后的基础处理方法 diff --git a/pages/index/gesture-handler.js b/pages/index/gesture-handler.js index c2e267c..7ad20a2 100644 --- a/pages/index/gesture-handler.js +++ b/pages/index/gesture-handler.js @@ -163,22 +163,28 @@ class GestureHandler { } // 基础平移手势处理 _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}; + // 获取容器坐标系坐标(统一计算方法) + 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]; diff --git a/pages/index/transform-canvas.vue b/pages/index/transform-canvas.vue index 72a0c1d..973a579 100644 --- a/pages/index/transform-canvas.vue +++ b/pages/index/transform-canvas.vue @@ -32,10 +32,10 @@ export default { canvasContext: null, image: null, dpr: 1, - canvasDisplayWidth: 300, // 默认显示尺寸 - canvasDisplayHeight: 300, - canvasActualWidth: 300, // 实际像素尺寸 - canvasActualHeight: 300 + canvasDisplayWidth: 800, // 默认显示尺寸 + canvasDisplayHeight: 600, + canvasActualWidth: 800, // 实际像素尺寸 + canvasActualHeight: 600 }; }, watch: { @@ -58,15 +58,12 @@ export default { immediate: true }, matrix: { - deep: true, - handler() { - this.$nextTick(() => { - if (this.canvasContext) { - this.redraw(); - } - }); - } - } + deep: true, + immediate: true, // 添加立即触发 + handler() { + this.$nextTick(this.redraw); // 确保在下一个tick重绘 + } + }, }, mounted() { this.initCanvas(); @@ -136,6 +133,7 @@ export default { // 重置为初始状态 this.ctx.resetTransform(); + console.log(this.canvasActualWidth, this.canvasActualHeight,'123123123123') this.ctx.clearRect(0, 0, this.canvasActualWidth, this.canvasActualHeight); // 应用设备像素比缩放 @@ -156,12 +154,12 @@ export default { ); } else { // 图片加载失败的占位图 - this.ctx.fillStyle = '#f0f0f0'; - this.ctx.fillRect(0, 0, this.width, this.height); - this.ctx.fillStyle = '#999'; - this.ctx.textAlign = 'center'; - this.ctx.textBaseline = 'middle'; - this.ctx.fillText('图片加载失败', this.width / 2, this.height / 2); + // this.ctx.fillStyle = '#f0f0f0'; + // this.ctx.fillRect(0, 0, this.width, this.height); + // this.ctx.fillStyle = '#999'; + // this.ctx.textAlign = 'center'; + // this.ctx.textBaseline = 'middle'; + // this.ctx.fillText('图片加载失败', this.width / 2, this.height / 2); } // 恢复上下文状态 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 7c78ca3..05ddfb4 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 30e4872..9da4ca4 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\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 +{"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 // 获取容器坐标系坐标(统一计算方法)\n const getPoint = (t) => ({\n x: t.x || (t.clientX - this.containerRect.left),\n y: t.y || (t.clientY - this.containerRect.top)\n });\n \n const currentPoint = getPoint(touch);\n \n if (this.lastPoint) {\n // 计算增量(使用容器坐标系)\n const dx = currentPoint.x - this.lastPoint.x;\n const dy = currentPoint.y - this.lastPoint.y;\n \n // 应用平移变换\n this.transformMatrix.tx += dx;\n this.transformMatrix.ty += dy;\n }\n \n // 存储当前点\n this.lastPoint = currentPoint;\n }\n\t\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 5f948db..698fdfe 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 b4a4e44..622a675 100644 --- a/unpackage/dist/dev/mp-weixin/common/vendor.js +++ b/unpackage/dist/dev/mp-weixin/common/vendor.js @@ -6880,9 +6880,9 @@ function initOnError() { }; } function initRuntimeSocketService() { - const hosts = "127.0.0.1,172.10.0.205"; + const hosts = "127.0.0.1,172.10.0.226"; const port = "8090"; - const id = "mp-weixin_Z7-NJ2"; + const id = "mp-weixin_YSvwpn"; 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 d708a1e..fa981ef 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 @@ -9,8 +9,8 @@ const _sfc_main = { }, data() { return { - canvasWidth: 300, - canvasHeight: 300, + canvasWidth: 800, + canvasHeight: 600, transformMatrix: new pages_index_transformMatrix.TransformMatrix(), gestureHandler: null, containerRect: null, @@ -96,9 +96,7 @@ const _sfc_main = { this.updateCanvas(); return; } - if (this.gestureHandler) { - return this.handleTouchEvent(event); - } + this.gestureHandler.catchEvent(event); if (!this.at) { if (correctedEvent.touches.length === 1) { this.handlePan(correctedEvent.touches[0]); @@ -113,7 +111,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:182", `原始坐标: (${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, 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 1615762..3464885 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/gesture-handler.js +++ b/unpackage/dist/dev/mp-weixin/pages/index/gesture-handler.js @@ -117,14 +117,18 @@ class GestureHandler { } // 基础平移手势处理 _handlePan(touch) { - const pointX = touch.x || touch.clientX - this.containerRect.left; - const pointY = touch.y || touch.clientY - this.containerRect.top; + 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 = pointX - this.lastPoint.x; - const dy = pointY - this.lastPoint.y; - this.transformMatrix.translate(dx, dy); + const dx = currentPoint.x - this.lastPoint.x; + const dy = currentPoint.y - this.lastPoint.y; + this.transformMatrix.tx += dx; + this.transformMatrix.ty += dy; } - this.lastPoint = { x: pointX, y: pointY }; + this.lastPoint = currentPoint; } // 基础缩放手势处理 _handlePinch(touches) { 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 5bc4a22..9bec86f 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js +++ b/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js @@ -26,12 +26,12 @@ const _sfc_main = { canvasContext: null, image: null, dpr: 1, - canvasDisplayWidth: 300, + canvasDisplayWidth: 800, // 默认显示尺寸 - canvasDisplayHeight: 300, - canvasActualWidth: 300, + canvasDisplayHeight: 600, + canvasActualWidth: 800, // 实际像素尺寸 - canvasActualHeight: 300 + canvasActualHeight: 600 }; }, watch: { @@ -56,12 +56,10 @@ const _sfc_main = { }, matrix: { deep: true, + immediate: true, + // 添加立即触发 handler() { - this.$nextTick(() => { - if (this.canvasContext) { - this.redraw(); - } - }); + this.$nextTick(this.redraw); } } }, @@ -105,7 +103,7 @@ const _sfc_main = { }); this.redraw(); } catch (e) { - common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:125", "图片加载失败:", e); + common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:122", "图片加载失败:", e); this.image = null; this.redraw(); } @@ -115,6 +113,7 @@ const _sfc_main = { return; this.ctx.save(); this.ctx.resetTransform(); + common_vendor.index.__f__("log", "at pages/index/transform-canvas.vue:136", this.canvasActualWidth, this.canvasActualHeight, "123123123123"); this.ctx.clearRect(0, 0, this.canvasActualWidth, this.canvasActualHeight); this.ctx.scale(this.dpr, this.dpr); const { a, b, c, d, tx, ty } = this.matrix; @@ -127,13 +126,6 @@ const _sfc_main = { this.canvasDisplayWidth, this.canvasDisplayHeight ); - } else { - this.ctx.fillStyle = "#f0f0f0"; - this.ctx.fillRect(0, 0, this.width, this.height); - this.ctx.fillStyle = "#999"; - this.ctx.textAlign = "center"; - this.ctx.textBaseline = "middle"; - this.ctx.fillText("图片加载失败", this.width / 2, this.height / 2); } this.ctx.restore(); }