选区选座

This commit is contained in:
sunmeng 2025-08-12 18:01:11 +08:00
parent 40437fd728
commit a0129fa7ce
13 changed files with 1025 additions and 269 deletions

File diff suppressed because one or more lines are too long

View File

@ -161,6 +161,13 @@ class GestureHandler {
// 公共接口
catchEvent(event) {
// 当触摸点数量变化时终止当前手势
if (this.lastTouchCount !== event.touches.length) {
this.panStarted = false;
this.lastPoints = null;
}
this.lastTouchCount = event.touches.length;
try {
if (this.at) {
this.at.run(event);

View File

@ -26,7 +26,8 @@ export default {
a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0
})
},
areaData:{}
areaData:{},
seatData:{}
},
data() {
return {
@ -65,6 +66,18 @@ export default {
this.$nextTick(this.redraw); // tick
}
},
areaData: {
deep: true,
handler() {
this.$nextTick(this.redraw);
}
},
seatData: {
deep: true,
handler() {
this.$nextTick(this.redraw);
}
}
},
mounted() {
this.initCanvas();
@ -75,77 +88,37 @@ export default {
if (!this.areaData) return null;
//
const inverted = this.matrix.invertPoint(x, y);
const inverted = this.matrix.invertPoint(x, y, this.dpr);
console.log('checkHitArea',inverted)
//
for (const area of this.areaData) {
if (this.pointInPolygon(inverted.x, inverted.y, area.polygon)) {
return area.areacode;
return area;
}
}
return null;
},
// 线
// pointInPolygon(x, y, polygon) {
// // console.log('pointInPolygon',x, y, polygon)
// //
// if (!polygon || polygon.length < 6) return false;
// let inside = false;
// const length = polygon.length;
// //
// for (let i = 0, j = length - 2; i < length; j = i, i += 2) {
// const xi = polygon[i], yi = polygon[i + 1];
// const xj = polygon[j], yj = polygon[j + 1];
// // y
// const intersect = ((yi > y) !== (yj > y));
// //
// if (intersect) {
// const slope = (xj - xi) / (yj - yi); //
// const intersectX = xi + (y - yi) * slope;
// if (x < intersectX) {
// inside = !inside;
// }
// }
// }
// return inside;
// },
// transform-canvas.vue pointInPolygon
pointInPolygon(x, y, polygon) {
// 3
if (!polygon || polygon.length < 6 || polygon.length % 2 !== 0) {
return false;
const points = [];
for (let i = 0; i < polygon.length; i += 2) {
points.push([polygon[i], polygon[i + 1]]);
}
let inside = false;
//
const vertexCount = polygon.length / 2;
let j = vertexCount - 1;
let j = points.length - 1;
for (let i = 0; i < vertexCount; j = i++) {
//
const xi = polygon[i * 2];
const yi = polygon[i * 2 + 1];
const xj = polygon[j * 2];
const yj = polygon[j * 2 + 1];
for (let i = 0; i < points.length; j = i++) {
const [xi, yi] = points[i];
const [xj, yj] = points[j];
// -
const onLine = this.pointOnLineSegment(x, y, xi, yi, xj, yj);
if (onLine) return true;
// 线
if (this.pointOnLineSegment(x, y, xi, yi, xj, yj)) return true;
// 线
if ((yi < y && yj >= y) || (yj < y && yi >= y)) {
// 线
// 线
if (yi <= y && yj > y || yj <= y && yi > y) {
const slope = (xj - xi) / (yj - yi);
const intersectX = xi + (y - yi) * slope;
// 穿
if (x < intersectX) {
if (x <= xi + (y - yi) * slope) {
inside = !inside;
}
}
@ -154,6 +127,8 @@ export default {
return inside;
},
// 线
pointOnLineSegment(x, y, x1, y1, x2, y2) {
// 线
@ -178,7 +153,7 @@ export default {
const projY = y1 + t * dy;
// 5px
const distance = Math.sqrt((x - projX) ** 2 + (y - projY) ** 2);
const distance = Math.sqrt((x - projX) * 2 + (y - projY) * 2);
return distance < 5;
}
@ -212,15 +187,16 @@ export default {
// 使propwidth/height
this.canvasDisplayWidth = this.width;
this.canvasDisplayHeight = this.height;
// * this.dpr
// * this.dpr
// DPR
this.canvasActualWidth = this.width * this.dpr;
this.canvasActualHeight = this.height * this.dpr;
this.canvasActualWidth = this.width;
this.canvasActualHeight = this.height;
if (this.canvas) {
this.canvas.width = this.canvasActualWidth;
this.canvas.height = this.canvasActualHeight;
this.ctx.scale(this.dpr, this.dpr);
// this.ctx.scale(this.dpr, this.dpr);
this.redraw();
}
},
@ -249,77 +225,103 @@ export default {
}
},
// 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) {
// console.error(":", e);
// this.image = null;
// this.redraw(); //
// }
// },
// redraw
checkSeatHit(x, y) {
if (!this.seatData) return null;
redraw() {
if (!this.ctx) return;
//
const inverted = this.matrix.invertPoint(x, y, this.dpr);
//
this.ctx.save();
//
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);
//
this.ctx.resetTransform();
this.ctx.clearRect(0, 0, this.canvasActualWidth, this.canvasActualHeight);
// 8px
if (distance < 8) {
return seat;
}
}
return null;
},
redraw() {
if (!this.ctx) return;
//
this.ctx.scale(this.dpr, this.dpr);
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);
//
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
);
}
// this.ctx.restore();
//
if (this.image && this.$parent?.currentView === 'area') {
this.ctx.drawImage(
this.image,
0,
0,
this.canvasDisplayWidth,
this.canvasDisplayHeight
);
}
//
if (this.areaData && this.areaData.length > 0) {
this.areaData.forEach(area => {
// if (!area.polygon || area.polygon.length < 6) return;
//
if (this.areaData && this.areaData.length > 0 && this.$parent?.currentView === 'area') {
this.drawAreas();
}
this.ctx.beginPath();
//
if (this.seatData && this.seatData.length > 0 && this.$parent?.currentView === 'seat') {
this.drawSeats();
}
for (let i = 0; i < area.polygon.length; i += 2) {
// 使API
if (i === 0) {
this.ctx.moveTo(area.polygon[i], area.polygon[i + 1]);
} else {
this.ctx.lineTo(area.polygon[i], area.polygon[i + 1]);
}
}
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.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();
});
}
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();
//
});
}
}
}
</script>

View File

@ -61,20 +61,17 @@ class TransformMatrix {
}
// 添加逆矩阵转换方法
invertPoint(x, y) {
const det = this.a * this.d - this.b * this.c;
invertPoint(x, y, dpr) {
console.log('invertPoint',dpr)
const det = this.a * this.d - this.b * this.c;
if (Math.abs(det) < 0.0001) return {x, y};
// 确保行列式不为零
if (Math.abs(det) < 0.0001) {
return {x, y}; // 避免除以零的错误
}
// 使用正确的逆变换公式
return {
x: (this.d * (x - this.tx) - this.c * (y - this.ty)) / det,
y: (this.a * (y - this.ty) - this.b * (x - this.tx)) / det
};
return {
x: (this.d * (x/dpr - this.tx) - this.c * (y/dpr - this.ty)) / det,
y: (this.a * (y/dpr - this.ty) - this.b * (x/dpr - this.tx)) / det
};
}
}
export default TransformMatrix;

View File

@ -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;"}
{"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;"}

File diff suppressed because one or more lines are too long

View File

@ -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;"}
{"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;"}

View File

@ -1 +1 @@
{"version":3,"file":"transform-matrix.js","sources":["pages/index/transform-matrix.js"],"sourcesContent":["class TransformMatrix {\n constructor() {\n this.reset();\n }\n \n reset() {\n this.a = 1; // 水平缩放\n this.b = 0; // 垂直倾斜\n this.c = 0; // 水平倾斜\n this.d = 1; // 垂直缩放\n this.tx = 0; // 水平移动\n this.ty = 0; // 垂直移动\n this.stack = [];\n }\n \n translate(dx, dy) {\n this.tx += this.a * dx + this.c * dy;\n this.ty += this.b * dx + this.d * dy;\n }\n \n scale(sx, sy, cx = 0, cy = 0) {\n // 移动到中心点\n this.translate(cx, cy);\n \n // 应用缩放\n this.a *= sx;\n this.b *= sx;\n this.c *= sy;\n this.d *= sy;\n \n // 移回原位置\n this.translate(-cx, -cy);\n }\n \n toArray() {\n return [this.a, this.b, this.c, this.d, this.tx, this.ty];\n }\n \n // 用于调试的字符串表示\n toString() {\n return `[${this.a.toFixed(2)}, ${this.b.toFixed(2)}, ${this.c.toFixed(2)}, ${this.d.toFixed(2)}, ${this.tx.toFixed(1)}, ${this.ty.toFixed(1)}]`;\n }\n \n // 克隆方法\n clone() {\n const clone = new TransformMatrix();\n clone.a = this.a;\n clone.b = this.b;\n clone.c = this.c;\n clone.d = this.d;\n clone.tx = this.tx;\n clone.ty = this.ty;\n return clone;\n }\n\t// 添加点坐标转换方法\n\ttransformPoint(x, y) {\n\t\treturn {\n\t\t\tx: this.a * x + this.c * y + this.tx,\n\t\t\ty: this.b * x + this.d * y + this.ty\n\t\t};\n\t}\n\t\n\t// 添加逆矩阵转换方法\n\tinvertPoint(x, y) {\n\t\tconst det = this.a * this.d - this.b * this.c;\n\t\t\n\t\t// 确保行列式不为零\n\t\tif (Math.abs(det) < 0.0001) {\n\t\t\treturn {x, y}; // 避免除以零的错误\n\t\t}\n\t\t\n\t\t// 使用正确的逆变换公式\n\t\treturn {\n\t\t\tx: (this.d * (x - this.tx) - this.c * (y - this.ty)) / det,\n\t\t\ty: (this.a * (y - this.ty) - this.b * (x - this.tx)) / det\n\t\t};\n\t}\n}\n\nexport default TransformMatrix;"],"names":[],"mappings":";AAAA,MAAM,gBAAgB;AAAA,EACpB,cAAc;AACZ,SAAK,MAAK;AAAA,EACX;AAAA,EAED,QAAQ;AACN,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,QAAQ;EACd;AAAA,EAED,UAAU,IAAI,IAAI;AAChB,SAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI;AAClC,SAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI;AAAA,EACnC;AAAA,EAED,MAAM,IAAI,IAAI,KAAK,GAAG,KAAK,GAAG;AAE5B,SAAK,UAAU,IAAI,EAAE;AAGrB,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK;AAGV,SAAK,UAAU,CAAC,IAAI,CAAC,EAAE;AAAA,EACxB;AAAA,EAED,UAAU;AACR,WAAO,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,EAAE;AAAA,EACzD;AAAA;AAAA,EAGD,WAAW;AACT,WAAO,IAAI,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,GAAG,QAAQ,CAAC,CAAC,KAAK,KAAK,GAAG,QAAQ,CAAC,CAAC;AAAA,EAC7I;AAAA;AAAA,EAGD,QAAQ;AACN,UAAM,QAAQ,IAAI;AAClB,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,KAAK;AACf,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,KAAK;AAChB,WAAO;AAAA,EACR;AAAA;AAAA,EAEF,eAAe,GAAG,GAAG;AACpB,WAAO;AAAA,MACN,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK;AAAA,MAClC,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK;AAAA,IACrC;AAAA,EACE;AAAA;AAAA,EAGD,YAAY,GAAG,GAAG;AACjB,UAAM,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AAG5C,QAAI,KAAK,IAAI,GAAG,IAAI,MAAQ;AAC3B,aAAO,EAAC,GAAG,EAAC;AAAA,IACZ;AAGD,WAAO;AAAA,MACN,IAAI,KAAK,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK,IAAI,KAAK,OAAO;AAAA,MACvD,IAAI,KAAK,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK,IAAI,KAAK,OAAO;AAAA,IAC1D;AAAA,EACE;AACF;;"}
{"version":3,"file":"transform-matrix.js","sources":["pages/index/transform-matrix.js"],"sourcesContent":["class TransformMatrix {\n constructor() {\n this.reset();\n }\n \n reset() {\n this.a = 1; // 水平缩放\n this.b = 0; // 垂直倾斜\n this.c = 0; // 水平倾斜\n this.d = 1; // 垂直缩放\n this.tx = 0; // 水平移动\n this.ty = 0; // 垂直移动\n this.stack = [];\n }\n \n translate(dx, dy) {\n this.tx += this.a * dx + this.c * dy;\n this.ty += this.b * dx + this.d * dy;\n }\n \n scale(sx, sy, cx = 0, cy = 0) {\n // 移动到中心点\n this.translate(cx, cy);\n \n // 应用缩放\n this.a *= sx;\n this.b *= sx;\n this.c *= sy;\n this.d *= sy;\n \n // 移回原位置\n this.translate(-cx, -cy);\n }\n \n toArray() {\n return [this.a, this.b, this.c, this.d, this.tx, this.ty];\n }\n \n // 用于调试的字符串表示\n toString() {\n return `[${this.a.toFixed(2)}, ${this.b.toFixed(2)}, ${this.c.toFixed(2)}, ${this.d.toFixed(2)}, ${this.tx.toFixed(1)}, ${this.ty.toFixed(1)}]`;\n }\n \n // 克隆方法\n clone() {\n const clone = new TransformMatrix();\n clone.a = this.a;\n clone.b = this.b;\n clone.c = this.c;\n clone.d = this.d;\n clone.tx = this.tx;\n clone.ty = this.ty;\n return clone;\n }\n\t// 添加点坐标转换方法\n\ttransformPoint(x, y) {\n\t\treturn {\n\t\t\tx: this.a * x + this.c * y + this.tx,\n\t\t\ty: this.b * x + this.d * y + this.ty\n\t\t};\n\t}\n\t\n\t// 添加逆矩阵转换方法\n\tinvertPoint(x, y, dpr) {\n\t\tconsole.log('invertPoint',dpr)\n\t const det = this.a * this.d - this.b * this.c;\n\t if (Math.abs(det) < 0.0001) return {x, y};\n\t \n\t return {\n\t x: (this.d * (x/dpr - this.tx) - this.c * (y/dpr - this.ty)) / det,\n\t y: (this.a * (y/dpr - this.ty) - this.b * (x/dpr - this.tx)) / det\n\t };\n\t}\n\t\n}\n\nexport default TransformMatrix;"],"names":["uni"],"mappings":";;AAAA,MAAM,gBAAgB;AAAA,EACpB,cAAc;AACZ,SAAK,MAAK;AAAA,EACX;AAAA,EAED,QAAQ;AACN,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,QAAQ;EACd;AAAA,EAED,UAAU,IAAI,IAAI;AAChB,SAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI;AAClC,SAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI;AAAA,EACnC;AAAA,EAED,MAAM,IAAI,IAAI,KAAK,GAAG,KAAK,GAAG;AAE5B,SAAK,UAAU,IAAI,EAAE;AAGrB,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK;AAGV,SAAK,UAAU,CAAC,IAAI,CAAC,EAAE;AAAA,EACxB;AAAA,EAED,UAAU;AACR,WAAO,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,EAAE;AAAA,EACzD;AAAA;AAAA,EAGD,WAAW;AACT,WAAO,IAAI,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,GAAG,QAAQ,CAAC,CAAC,KAAK,KAAK,GAAG,QAAQ,CAAC,CAAC;AAAA,EAC7I;AAAA;AAAA,EAGD,QAAQ;AACN,UAAM,QAAQ,IAAI;AAClB,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,KAAK;AACf,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,KAAK;AAChB,WAAO;AAAA,EACR;AAAA;AAAA,EAEF,eAAe,GAAG,GAAG;AACpB,WAAO;AAAA,MACN,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK;AAAA,MAClC,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK;AAAA,IACrC;AAAA,EACE;AAAA;AAAA,EAGD,YAAY,GAAG,GAAG,KAAK;AACtBA,kBAAAA,4DAAY,gBAAe,GAAG;AAC7B,UAAM,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AAC5C,QAAI,KAAK,IAAI,GAAG,IAAI;AAAQ,aAAO,EAAC,GAAG,EAAC;AAExC,WAAO;AAAA,MACL,IAAI,KAAK,KAAK,IAAE,MAAM,KAAK,MAAM,KAAK,KAAK,IAAE,MAAM,KAAK,OAAO;AAAA,MAC/D,IAAI,KAAK,KAAK,IAAE,MAAM,KAAK,MAAM,KAAK,KAAK,IAAE,MAAM,KAAK,OAAO;AAAA,IACpE;AAAA,EACE;AAEF;;"}

View File

@ -6882,7 +6882,7 @@ function initOnError() {
function initRuntimeSocketService() {
const hosts = "127.0.0.1,172.10.0.127";
const port = "8090";
const id = "mp-weixin_IDV0HS";
const id = "mp-weixin_8j0jyd";
const lazy = typeof swan !== "undefined";
let restoreError = lazy ? () => {
} : initOnError();

File diff suppressed because one or more lines are too long

View File

@ -123,6 +123,11 @@ class GestureHandler {
}
// 公共接口
catchEvent(event) {
if (this.lastTouchCount !== event.touches.length) {
this.panStarted = false;
this.lastPoints = null;
}
this.lastTouchCount = event.touches.length;
try {
if (this.at) {
this.at.run(event);
@ -130,7 +135,7 @@ class GestureHandler {
this.catchEvent(event);
}
} catch (e) {
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:171", "手势处理错误:", e);
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:178", "手势处理错误:", e);
}
}
// 基础平移手势处理

View File

@ -20,7 +20,8 @@ const _sfc_main = {
ty: 0
})
},
areaData: {}
areaData: {},
seatData: {}
},
data() {
return {
@ -62,6 +63,18 @@ const _sfc_main = {
handler() {
this.$nextTick(this.redraw);
}
},
areaData: {
deep: true,
handler() {
this.$nextTick(this.redraw);
}
},
seatData: {
deep: true,
handler() {
this.$nextTick(this.redraw);
}
}
},
mounted() {
@ -72,59 +85,30 @@ const _sfc_main = {
checkHitArea(x, y) {
if (!this.areaData)
return null;
const inverted = this.matrix.invertPoint(x, y);
common_vendor.index.__f__("log", "at pages/index/transform-canvas.vue:79", "checkHitArea", inverted);
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.areacode;
return area;
}
}
return null;
},
// 射线法判断点是否在多边形内
// pointInPolygon(x, y, polygon) {
// // uni.__f__('log','at pages/index/transform-canvas.vue:90','pointInPolygon',x, y, polygon)
// // 确保多边形有足够的点构成
// if (!polygon || polygon.length < 6) return false;
// let inside = false;
// const length = polygon.length;
// // 不需要遍历最后一个点,因为它是闭合点(与第一个点相同)
// for (let i = 0, j = length - 2; i < length; j = i, i += 2) {
// const xi = polygon[i], yi = polygon[i + 1];
// const xj = polygon[j], yj = polygon[j + 1];
// // 检查点是否在边的y值范围内
// const intersect = ((yi > y) !== (yj > y));
// // 检查点是否在边的左侧
// if (intersect) {
// const slope = (xj - xi) / (yj - yi); // 边的斜率
// const intersectX = xi + (y - yi) * slope;
// if (x < intersectX) {
// inside = !inside;
// }
// }
// }
// return inside;
// },
// 在 transform-canvas.vue 中替换 pointInPolygon 方法
pointInPolygon(x, y, polygon) {
if (!polygon || polygon.length < 6 || polygon.length % 2 !== 0) {
return false;
const points = [];
for (let i = 0; i < polygon.length; i += 2) {
points.push([polygon[i], polygon[i + 1]]);
}
let inside = false;
const vertexCount = polygon.length / 2;
let j = vertexCount - 1;
for (let i = 0; i < vertexCount; j = i++) {
const xi = polygon[i * 2];
const yi = polygon[i * 2 + 1];
const xj = polygon[j * 2];
const yj = polygon[j * 2 + 1];
const onLine = this.pointOnLineSegment(x, y, xi, yi, xj, yj);
if (onLine)
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) {
if (yi <= y && yj > y || yj <= y && yi > y) {
const slope = (xj - xi) / (yj - yi);
const intersectX = xi + (y - yi) * slope;
if (x < intersectX) {
if (x <= xi + (y - yi) * slope) {
inside = !inside;
}
}
@ -143,7 +127,7 @@ const _sfc_main = {
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);
const distance = Math.sqrt((x - projX) * 2 + (y - projY) * 2);
return distance < 5;
}
return false;
@ -165,12 +149,11 @@ const _sfc_main = {
updateCanvasSize() {
this.canvasDisplayWidth = this.width;
this.canvasDisplayHeight = this.height;
this.canvasActualWidth = this.width * this.dpr;
this.canvasActualHeight = this.height * this.dpr;
this.canvasActualWidth = this.width;
this.canvasActualHeight = this.height;
if (this.canvas) {
this.canvas.width = this.canvasActualWidth;
this.canvas.height = this.canvasActualHeight;
this.ctx.scale(this.dpr, this.dpr);
this.redraw();
}
},
@ -190,26 +173,27 @@ const _sfc_main = {
});
this.redraw();
} catch (e) {
common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:247", "图片加载失败:", e);
common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:223", "图片加载失败:", e);
this.image = null;
}
},
// 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) {
// uni.__f__('error','at pages/index/transform-canvas.vue:262',"图片加载失败:", e);
// this.image = null;
// this.redraw(); // 加载失败时也需要重绘画布
// }
// },
// 在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();
@ -218,7 +202,7 @@ const _sfc_main = {
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) {
if (this.image && ((_a = this.$parent) == null ? void 0 : _a.currentView) === "area") {
this.ctx.drawImage(
this.image,
0,
@ -227,24 +211,47 @@ const _sfc_main = {
this.canvasDisplayHeight
);
}
if (this.areaData && this.areaData.length > 0) {
this.areaData.forEach((area) => {
this.ctx.beginPath();
for (let i = 0; i < area.polygon.length; i += 2) {
if (i === 0) {
this.ctx.moveTo(area.polygon[i], area.polygon[i + 1]);
} else {
this.ctx.lineTo(area.polygon[i], area.polygon[i + 1]);
}
}
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();
});
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();
});
}
}
};

View File

@ -1,4 +1,5 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
class TransformMatrix {
constructor() {
this.reset();
@ -50,14 +51,14 @@ class TransformMatrix {
};
}
// 添加逆矩阵转换方法
invertPoint(x, y) {
invertPoint(x, y, dpr) {
common_vendor.index.__f__("log", "at pages/index/transform-matrix.js:65", "invertPoint", dpr);
const det = this.a * this.d - this.b * this.c;
if (Math.abs(det) < 1e-4) {
if (Math.abs(det) < 1e-4)
return { x, y };
}
return {
x: (this.d * (x - this.tx) - this.c * (y - this.ty)) / det,
y: (this.a * (y - this.ty) - this.b * (x - this.tx)) / det
x: (this.d * (x / dpr - this.tx) - this.c * (y / dpr - this.ty)) / det,
y: (this.a * (y / dpr - this.ty) - this.b * (x / dpr - this.tx)) / det
};
}
}