diff --git a/pages/index/gesture-canvas-page.vue b/pages/index/gesture-canvas-page.vue index 31f4694..f6669a8 100644 --- a/pages/index/gesture-canvas-page.vue +++ b/pages/index/gesture-canvas-page.vue @@ -18,6 +18,7 @@ :width="canvasWidth" :height="canvasHeight" :matrix="transformMatrix" + :imgUrl="'https://assets.tech.troyrc.com/sx25/images/events/XBDT.jpg'" /> @@ -220,7 +221,7 @@ export default { this.$nextTick(() => { const canvas = this.$refs.canvasRef; if (canvas) { - canvas.draw(); + // canvas.draw(); // 计算当前缩放值 this.scaleValue = Math.sqrt( diff --git a/pages/index/transform-canvas.vue b/pages/index/transform-canvas.vue index 5a281a5..72a0c1d 100644 --- a/pages/index/transform-canvas.vue +++ b/pages/index/transform-canvas.vue @@ -1,154 +1,172 @@ + \ 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 3a41822..5f948db 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 def1e28..b4a4e44 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_aMdMwA"; + const id = "mp-weixin_Z7-NJ2"; 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 af6efec..d708a1e 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,7 +35,7 @@ const _sfc_main = { container: this.containerRect }); } catch (e) { - common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:76", "手势处理器初始化失败:", e); + common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:77", "手势处理器初始化失败:", e); this.gestureHandler = { catchEvent: (event) => { if (event.touches.length > 0) { @@ -72,21 +72,21 @@ const _sfc_main = { width: rect.width, height: rect.height }; - common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:123", "成功获取容器位置:", this.containerRect); + common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:124", "成功获取容器位置:", this.containerRect); return; } } catch (e) { - common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:127", "获取容器位置失败:", e); + common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:128", "获取容器位置失败:", e); } await new Promise((r) => setTimeout(r, 100)); retryCount++; } - common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:135", `容器位置获取失败,已重试${maxRetries}次`); + common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:136", `容器位置获取失败,已重试${maxRetries}次`); }, // 事件处理 async handleTouchEvent(event) { if (!this.gestureHandler || !this.containerRect) { - common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:141", "手势处理器未就绪,尝试重新初始化..."); + common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:142", "手势处理器未就绪,尝试重新初始化..."); await this.getContainerPosition(); this.initGestureHandler(); if (event.type === "touchend" || event.type === "touchcancel") { @@ -113,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:181", `原始坐标: (${touch.clientX}, ${touch.clientY}) 修正后: (${x}, ${y})`); + common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:182", `原始坐标: (${touch.clientX}, ${touch.clientY}) 修正后: (${x}, ${y})`); return { ...touch, x, @@ -143,7 +143,6 @@ const _sfc_main = { this.$nextTick(() => { const canvas = this.$refs.canvasRef; if (canvas) { - canvas.draw(); this.scaleValue = Math.sqrt( this.transformMatrix.a * this.transformMatrix.a + this.transformMatrix.b * this.transformMatrix.b ); @@ -184,7 +183,8 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { g: common_vendor.p({ width: $data.canvasWidth, height: $data.canvasHeight, - matrix: $data.transformMatrix + matrix: $data.transformMatrix, + imgUrl: "https://assets.tech.troyrc.com/sx25/images/events/XBDT.jpg" }), h: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)), i: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)), 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 778f5c0..5bc4a22 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js +++ b/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.js @@ -3,117 +3,146 @@ const common_vendor = require("../../common/vendor.js"); const _sfc_main = { props: { width: Number, + // 画布实际宽度(像素) height: Number, - matrix: Object + // 画布实际高度(像素) + imgUrl: String, + // 图片URL + matrix: { + // 变换矩阵 + type: Object, + default: () => ({ + a: 1, + b: 0, + c: 0, + d: 1, + tx: 0, + ty: 0 + }) + } }, data() { return { - ctx: null, - canvasWidth: this.width, - canvasHeight: this.height + canvasContext: null, + image: null, + dpr: 1, + canvasDisplayWidth: 300, + // 默认显示尺寸 + canvasDisplayHeight: 300, + canvasActualWidth: 300, + // 实际像素尺寸 + canvasActualHeight: 300 }; }, + watch: { + imgUrl: { + handler(newUrl) { + if (newUrl) + this.loadImage(newUrl); + }, + immediate: true + }, + width: { + handler() { + this.updateCanvasSize(); + }, + immediate: true + }, + height: { + handler() { + this.updateCanvasSize(); + }, + immediate: true + }, + matrix: { + deep: true, + handler() { + this.$nextTick(() => { + if (this.canvasContext) { + this.redraw(); + } + }); + } + } + }, mounted() { this.initCanvas(); }, methods: { initCanvas() { - this.ctx = common_vendor.index.createCanvasContext("gestureCanvas", this); - const pixelRatio = common_vendor.index.getSystemInfoSync().pixelRatio; - this.ctx.scale(pixelRatio, pixelRatio); + const query = common_vendor.index.createSelectorQuery().in(this); + query.select("#myCanvas").fields({ node: true, size: true }).exec(async (res) => { + if (!res[0]) + return; + this.canvas = res[0].node; + this.ctx = res[0].node.getContext("2d"); + this.dpr = common_vendor.index.getSystemInfoSync().pixelRatio; + this.updateCanvasSize(); + if (this.imgUrl) { + await this.loadImage(this.imgUrl); + } + }); }, - applyTransform(matrix) { - if (!matrix) - return; - const pixelRatio = common_vendor.index.getSystemInfoSync().pixelRatio; - const tx = matrix.tx * pixelRatio; - const ty = matrix.ty * pixelRatio; - this.ctx.setTransform( - matrix.a, - matrix.b, - matrix.c, - matrix.d, - tx, - ty - ); - }, - // 调试网格 - // 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) { - common_vendor.index.__f__("warn", "at pages/index/transform-canvas.vue:110", "Canvas上下文未初始化"); - return; + updateCanvasSize() { + this.canvasDisplayWidth = this.width; + this.canvasDisplayHeight = this.height; + this.canvasActualWidth = this.width * this.dpr; + this.canvasActualHeight = this.height * this.dpr; + if (this.canvas) { + this.canvas.width = this.canvasActualWidth; + this.canvas.height = this.canvasActualHeight; + this.ctx.scale(this.dpr, this.dpr); + this.redraw(); } - this.clearCanvas(); - this.applyTransform(this.matrix); - this.drawContent(); }, - clearCanvas() { - const pixelRatio = common_vendor.index.getSystemInfoSync().pixelRatio; - const width = this.canvasWidth * pixelRatio; - const height = this.canvasHeight * pixelRatio; - this.ctx.setTransform(1, 0, 0, 1, 0, 0); - this.ctx.clearRect(0, 0, width, height); + async loadImage(src) { + try { + this.image = await new Promise((resolve, reject) => { + const image = this.canvas.createImage(); + image.src = src; + image.onload = () => resolve(image); + image.onerror = reject; + }); + this.redraw(); + } catch (e) { + common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:125", "图片加载失败:", e); + this.image = null; + this.redraw(); + } }, - drawContent() { - this.ctx.fillStyle = "#3498db"; - this.ctx.fillRect(50, 50, 100, 100); - this.ctx.fillStyle = "#e74c3c"; - this.ctx.beginPath(); - this.ctx.arc(150, 150, 50, 0, 2 * Math.PI); - this.ctx.fill(); - this.ctx.fillStyle = "#2c3e50"; - this.ctx.font = "20px sans-serif"; - this.ctx.fillText("手势Canvas", 50, 250); - this.ctx.draw(); + redraw() { + if (!this.ctx) + return; + this.ctx.save(); + this.ctx.resetTransform(); + 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; + this.ctx.setTransform(a, b, c, d, tx, ty); + if (this.image) { + this.ctx.drawImage( + this.image, + 0, + 0, + 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(); } } }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return { - a: $data.canvasWidth + "px", - b: $data.canvasHeight + "px" + a: `${$data.canvasDisplayWidth}px`, + b: `${$data.canvasDisplayHeight}px` }; } const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]); diff --git a/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.wxml b/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.wxml index 3c1690e..23ce35e 100644 --- a/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.wxml +++ b/unpackage/dist/dev/mp-weixin/pages/index/transform-canvas.wxml @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file