"use strict"; const common_vendor = require("../../common/vendor.js"); const _sfc_main = { props: { width: Number, // 画布实际宽度(像素) height: Number, // 画布实际高度(像素) imgUrl: String, // 图片URL matrix: { // 变换矩阵 type: Object, default: () => ({ a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }) }, areaData: {}, seatData: {} }, data() { return { canvasContext: null, image: null, dpr: 1, canvasDisplayWidth: 800, // 默认显示尺寸 canvasDisplayHeight: 600, canvasActualWidth: 800, // 实际像素尺寸 canvasActualHeight: 600 }; }, 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, immediate: true, // 添加立即触发 handler() { this.$nextTick(this.redraw); } }, areaData: { deep: true, handler() { this.$nextTick(this.redraw); } }, seatData: { deep: true, handler() { this.$nextTick(this.redraw); } } }, mounted() { this.initCanvas(); }, methods: { // 添加点击检测方法 checkHitArea(x, y) { if (!this.areaData) return null; const inverted = this.matrix.invertPoint(x, y, this.dpr); common_vendor.index.__f__("log", "at pages/index/transform-canvas.vue:92", "checkHitArea", inverted); for (const area of this.areaData) { if (this.pointInPolygon(inverted.x, inverted.y, area.polygon)) { return area; } } return null; }, pointInPolygon(x, y, polygon) { const points = []; for (let i = 0; i < polygon.length; i += 2) { points.push([polygon[i], polygon[i + 1]]); } let inside = false; let j = points.length - 1; for (let i = 0; i < points.length; j = i++) { const [xi, yi] = points[i]; const [xj, yj] = points[j]; if (this.pointOnLineSegment(x, y, xi, yi, xj, yj)) return true; if (yi <= y && yj > y || yj <= y && yi > y) { const slope = (xj - xi) / (yj - yi); if (x <= xi + (y - yi) * slope) { inside = !inside; } } } return inside; }, // 添加点是否在线段上的检查 pointOnLineSegment(x, y, x1, y1, x2, y2) { const dx = x2 - x1; const dy = y2 - y1; const segmentLength = Math.sqrt(dx * dx + dy * dy); const vx = x - x1; const vy = y - y1; const dotProduct = vx * dx + vy * dy; const t = dotProduct / (segmentLength * segmentLength); if (t >= 0 && t <= 1) { const projX = x1 + t * dx; const projY = y1 + t * dy; const distance = Math.sqrt((x - projX) * 2 + (y - projY) * 2); return distance < 5; } return false; }, initCanvas() { 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); } }); }, updateCanvasSize() { this.canvasDisplayWidth = this.width; this.canvasDisplayHeight = this.height; this.canvasActualWidth = this.width; this.canvasActualHeight = this.height; if (this.canvas) { this.canvas.width = this.canvasActualWidth; this.canvas.height = this.canvasActualHeight; this.redraw(); } }, async loadImage(src) { try { if (!this.canvas) { await this.initCanvas(); } this.image = await new Promise((resolve, reject) => { if (!this.canvas) { return; } 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:223", "图片加载失败:", e); this.image = null; } }, // 在redraw方法中添加视图判断 checkSeatHit(x, y) { if (!this.seatData) return null; const inverted = this.matrix.invertPoint(x, y, this.dpr); for (const seat of this.seatData) { const dx = seat.x - inverted.x; const dy = seat.y - inverted.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < 8) { return seat; } } return null; }, redraw() { var _a, _b, _c; 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 && ((_a = this.$parent) == null ? void 0 : _a.currentView) === "area") { this.ctx.drawImage( this.image, 0, 0, this.canvasDisplayWidth, this.canvasDisplayHeight ); } if (this.areaData && this.areaData.length > 0 && ((_b = this.$parent) == null ? void 0 : _b.currentView) === "area") { this.drawAreas(); } if (this.seatData && this.seatData.length > 0 && ((_c = this.$parent) == null ? void 0 : _c.currentView) === "seat") { this.drawSeats(); } this.ctx.restore(); }, // 添加绘制区域方法 drawAreas() { this.areaData.forEach((area) => { const points = []; for (let i = 0; i < area.polygon.length; i += 2) { points.push([area.polygon[i], area.polygon[i + 1]]); } this.ctx.beginPath(); points.forEach(([x, y], index) => { if (index === 0) this.ctx.moveTo(x, y); else this.ctx.lineTo(x, y); }); this.ctx.closePath(); this.ctx.strokeStyle = "rgba(255, 0, 0, 0.7)"; this.ctx.lineWidth = 2; this.ctx.stroke(); this.ctx.fillStyle = "rgba(0, 255, 0, 0.2)"; this.ctx.fill(); }); }, drawSeats() { const scale = Math.sqrt(this.matrix.a * this.matrix.a + this.matrix.b * this.matrix.b); this.seatData.forEach((seat) => { const x = seat.x; const y = seat.y; this.ctx.beginPath(); const radius = 8 / scale; this.ctx.arc(x, y, radius, 0, Math.PI * 2); this.ctx.fillStyle = seat.status === 1 ? "#4cd964" : "#dd524d"; this.ctx.fill(); }); } } }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return { a: `${$data.canvasDisplayWidth}px`, b: `${$data.canvasDisplayHeight}px` }; } const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]); wx.createComponent(Component); //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/index/transform-canvas.js.map