选中
This commit is contained in:
parent
a0129fa7ce
commit
ed07181a5e
@ -21,6 +21,7 @@
|
||||
:imgUrl="'https://assets.tech.troyrc.com/sx25/images/events/XBDT.jpg'"
|
||||
:areaData="currentView === 'area' ? seatAreas : []"
|
||||
:seatData="currentView === 'seat' ? seatPositions : []"
|
||||
:selectedCodes="selectedCodes"
|
||||
/>
|
||||
</view>
|
||||
<!-- isShowSeat -->
|
||||
@ -57,7 +58,8 @@ export default {
|
||||
seatAreas: [], // 座位区域数据
|
||||
currentView:'area',
|
||||
seatPositions: [], // 座位数据
|
||||
selectedArea: null // 当前选中分区
|
||||
selectedArea: null, // 当前选中分区
|
||||
selectedCodes: new Set(), // 存储选中的座位code
|
||||
};
|
||||
},
|
||||
|
||||
@ -84,9 +86,10 @@ export default {
|
||||
// 计算点击坐标(考虑dpr)
|
||||
const x = (e.detail.x - this.containerRect.left) * dpr;
|
||||
const y = (e.detail.y - this.containerRect.top) * dpr;
|
||||
|
||||
console.log('handleCanvasClick',x,y)
|
||||
if (this.currentView === 'area') {
|
||||
const hitArea = this.$refs.canvasRef.checkHitArea(x, y);
|
||||
console.log('handleCanvasClick',hitArea)
|
||||
if (hitArea) {
|
||||
uni.showModal({
|
||||
title: '请确认',
|
||||
@ -99,7 +102,6 @@ export default {
|
||||
this.currentView = 'seat';
|
||||
this.loadSeatData(hitArea.areacode)
|
||||
}
|
||||
console.log(res,'showModa-- success')
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -107,12 +109,32 @@ export default {
|
||||
const hitSeat = this.$refs.canvasRef.checkSeatHit(x, y);
|
||||
if (hitSeat) {
|
||||
console.log('选中座位:', hitSeat);
|
||||
this.toggleSeatSelection(hitSeat);
|
||||
// 这里可以添加座位选择逻辑
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
toggleSeatSelection(seat) {
|
||||
if (seat.status !== 1) return; // 只允许选择可用座位
|
||||
|
||||
if (this.selectedCodes.has(seat.code)) {
|
||||
this.selectedCodes.delete(seat.code);
|
||||
} else {
|
||||
// 限制最多选择4个座位
|
||||
if (this.selectedCodes.size < 4) {
|
||||
this.selectedCodes.add(seat.code);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '最多只能选择4个座位',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
this.$refs.canvasRef.redraw(); // 触发重绘
|
||||
},
|
||||
|
||||
async getContainerPosition() {
|
||||
// 添加重试机制
|
||||
let retryCount = 0;
|
||||
@ -136,9 +158,9 @@ export default {
|
||||
};
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取容器位置失败:', e);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取容器位置失败:', e);
|
||||
}
|
||||
|
||||
// 等待后重试
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
@ -147,88 +169,110 @@ export default {
|
||||
},
|
||||
|
||||
initGestureHandler() {
|
||||
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) {
|
||||
this.gestureStatus = "降级模式";
|
||||
this.touchPoints = event.touches.length;
|
||||
try {
|
||||
this.gestureHandler = new GestureHandler(this, this.transformMatrix, {
|
||||
container: this.containerRect
|
||||
});
|
||||
console.log( 'initGestureHandler', this.gestureHandler )
|
||||
} catch (e) {
|
||||
console.error('手势处理器初始化失败:', e);
|
||||
// 简化降级方案
|
||||
this.gestureHandler = {
|
||||
catchEvent: this.createGestureFallback(),
|
||||
setScale: (scale) => {
|
||||
this.transformMatrix.scale(scale, scale, this.canvasWidth/2, this.canvasHeight/2);
|
||||
this.updateCanvas();
|
||||
},
|
||||
reset: () => {
|
||||
this.transformMatrix.reset();
|
||||
this.updateCanvas();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
if (event.type === 'touchmove') {
|
||||
const firstTouch = event.touches[0];
|
||||
const x = firstTouch.clientX - this.containerRect.left;
|
||||
const y = firstTouch.clientY - this.containerRect.top;
|
||||
createGestureFallback() {
|
||||
let isClick = true;
|
||||
let startPoint = null;
|
||||
let startTime = null;
|
||||
let lastPoint = null;
|
||||
|
||||
this.transformMatrix.tx = x;
|
||||
this.transformMatrix.ty = y;
|
||||
this.updateCanvas();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
return (event) => {
|
||||
const touches = event.touches || [];
|
||||
|
||||
// 事件处理
|
||||
async handleTouchEvent(event) {
|
||||
if (!this.gestureHandler || !this.containerRect) {
|
||||
await this.getContainerPosition();
|
||||
this.initGestureHandler();
|
||||
if (event.type === 'touchend' || event.type === 'touchcancel') {
|
||||
this.gestureStatus = '结束';
|
||||
this.updateCanvas();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (touches.length === 1) {
|
||||
const getPoint = (t) => ({
|
||||
x: t.clientX - this.containerRect.left,
|
||||
y: t.clientY - this.containerRect.top
|
||||
});
|
||||
|
||||
// 记录时间戳
|
||||
const currentTime = Date.now();
|
||||
const currentPoint = getPoint(touches[0]);
|
||||
|
||||
// 更新触点数量
|
||||
this.touchPoints = event.touches.length;
|
||||
if (!startPoint) {
|
||||
startPoint = currentPoint;
|
||||
startTime = Date.now();
|
||||
}
|
||||
|
||||
// 修正坐标
|
||||
const correctedTouches = Array.from(event.touches).map(touch => {
|
||||
return {
|
||||
...touch,
|
||||
x: touch.clientX - this.containerRect.left,
|
||||
y: touch.clientY - this.containerRect.top
|
||||
};
|
||||
});
|
||||
const dx = currentPoint.x - startPoint.x;
|
||||
const dy = currentPoint.y - startPoint.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
// 创建修正后的事件对象
|
||||
const correctedEvent = {
|
||||
...event,
|
||||
touches: correctedTouches,
|
||||
changedTouches: correctedTouches
|
||||
};
|
||||
// 如果是点击(移动距离小于阈值且时间短)
|
||||
if (isClick && distance < 5 && Date.now() - startTime < 200) {
|
||||
return; // 不执行移动操作
|
||||
}
|
||||
|
||||
// 传递事件给手势处理器
|
||||
this.gestureHandler.catchEvent(correctedEvent);
|
||||
// 标记为非点击操作
|
||||
isClick = false;
|
||||
|
||||
// 更新手势状态
|
||||
if (event.type === 'touchstart') {
|
||||
this.gestureStatus = event.touches.length > 1 ? '双指开始' : '单指开始';
|
||||
}
|
||||
else if (event.type === 'touchmove') {
|
||||
this.gestureStatus = event.touches.length > 1 ? '双指缩放/移动' : '单指移动';
|
||||
}
|
||||
else {
|
||||
this.gestureStatus = '结束';
|
||||
}
|
||||
// 执行移动操作
|
||||
if (lastPoint) {
|
||||
const moveDx = currentPoint.x - lastPoint.x;
|
||||
const moveDy = currentPoint.y - lastPoint.y;
|
||||
|
||||
// 限制更新频率
|
||||
if (currentTime - this.lastGestureTime > 50) {
|
||||
this.lastGestureTime = currentTime;
|
||||
this.updateCanvas();
|
||||
}
|
||||
},
|
||||
this.transformMatrix.tx += moveDx;
|
||||
this.transformMatrix.ty += moveDy;
|
||||
}
|
||||
|
||||
lastPoint = currentPoint;
|
||||
}
|
||||
|
||||
// 在触摸结束时重置状态
|
||||
if (event.type === 'touchend' || event.type === 'touchcancel') {
|
||||
isClick = true;
|
||||
startPoint = null;
|
||||
startTime = null;
|
||||
lastPoint = null;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
async handleTouchEvent(event) {
|
||||
console.log(event,'handleTouchEvent')
|
||||
// 更新触点数量
|
||||
this.touchPoints = event.touches.length;
|
||||
|
||||
// 仅在触摸开始时重置状态
|
||||
if (event.type === 'touchstart') {
|
||||
this.gestureStatus = event.touches.length > 1 ? '双指开始' : '单指开始';
|
||||
}
|
||||
|
||||
// 处理事件传递
|
||||
this.gestureHandler?.catchEvent(event);
|
||||
|
||||
// 更新触摸结束状态
|
||||
if (event.type === 'touchend' || event.type === 'touchcancel') {
|
||||
this.gestureStatus = '结束';
|
||||
this.updateCanvas();
|
||||
}
|
||||
|
||||
// 限制更新频率
|
||||
const currentTime = Date.now();
|
||||
if (currentTime - this.lastGestureTime > 50) {
|
||||
this.lastGestureTime = currentTime;
|
||||
this.updateCanvas();
|
||||
}
|
||||
},
|
||||
|
||||
// 更新Canvas
|
||||
updateCanvas() {
|
||||
@ -595,29 +639,37 @@ export default {
|
||||
this.transformMatrix = new TransformMatrix();
|
||||
|
||||
// 自动居中显示座位区域
|
||||
this.$nextTick(() => {
|
||||
if (this.seatPositions.length > 0) {
|
||||
const minX = Math.min(...this.seatPositions.map(s => s.x));
|
||||
const maxX = Math.max(...this.seatPositions.map(s => s.x));
|
||||
const minY = Math.min(...this.seatPositions.map(s => s.y));
|
||||
const maxY = Math.max(...this.seatPositions.map(s => s.y));
|
||||
// 自动居中显示座位区域
|
||||
this.$nextTick(() => {
|
||||
if (!this.gestureHandler) {
|
||||
this.initGestureHandler();
|
||||
}
|
||||
if (this.seatPositions.length > 0) {
|
||||
// 计算座位区域边界
|
||||
const xs = this.seatPositions.map(s => s.x);
|
||||
const ys = this.seatPositions.map(s => s.y);
|
||||
const minX = Math.min(...xs);
|
||||
const maxX = Math.max(...xs);
|
||||
const minY = Math.min(...ys);
|
||||
const maxY = Math.max(...ys);
|
||||
|
||||
const centerX = (minX + maxX) / 2;
|
||||
const centerY = (minY + maxY) / 2;
|
||||
// 计算中心点
|
||||
const centerX = (minX + maxX) / 2;
|
||||
const centerY = (minY + maxY) / 2;
|
||||
|
||||
// 计算合适的缩放比例
|
||||
const widthRatio = this.canvasWidth / (maxX - minX + 100);
|
||||
const heightRatio = this.canvasHeight / (maxY - minY + 100);
|
||||
const scale = Math.min(widthRatio, heightRatio, 1);
|
||||
// 计算合适的缩放比例
|
||||
const widthRatio = this.canvasWidth / (maxX - minX + 100);
|
||||
const heightRatio = this.canvasHeight / (maxY - minY + 100);
|
||||
const scale = Math.min(widthRatio, heightRatio, 1);
|
||||
|
||||
// 应用变换
|
||||
// this.transformMatrix.scale(scale, scale);
|
||||
// this.transformMatrix.translate(
|
||||
// this.canvasWidth/2 - centerX * scale,
|
||||
// this.canvasHeight/2 - centerY * scale
|
||||
// );
|
||||
}
|
||||
});
|
||||
// 应用变换
|
||||
// this.transformMatrix.scale(scale, scale);
|
||||
// this.transformMatrix.translate(
|
||||
// this.canvasWidth/2 - centerX * scale,
|
||||
// this.canvasHeight/2 - centerY * scale
|
||||
// );
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
} catch (e) {
|
||||
|
@ -4,7 +4,8 @@ class GestureHandler {
|
||||
this.containerRect = container;
|
||||
this.panThreshold = 5;
|
||||
this.panStarted = false;
|
||||
|
||||
// 保存父组件上下文
|
||||
this.context = context;
|
||||
// 判断是否是小程序环境
|
||||
this.isMiniProgram = typeof wx !== 'undefined' || typeof uni !== 'undefined';
|
||||
|
||||
@ -52,66 +53,63 @@ class GestureHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// 创建小程序专用的简化手势处理器
|
||||
createSimpleGestureHandler() {
|
||||
let isClick = true;
|
||||
let startPoint = null;
|
||||
let startTime = null;
|
||||
let lastPoint = null;
|
||||
createSimpleGestureHandler() {
|
||||
let isClick = true;
|
||||
let startPoint = null;
|
||||
let startTime = null;
|
||||
let lastPoint = null;
|
||||
|
||||
return (event) => {
|
||||
const touches = event.touches || [];
|
||||
return (event) => {
|
||||
// 移除了视图判断
|
||||
const touches = event.touches || [];
|
||||
|
||||
if (touches.length === 1) {
|
||||
const getPoint = (t) => ({
|
||||
x: t.x || (t.clientX - this.containerRect.left),
|
||||
y: t.y || (t.clientY - this.containerRect.top)
|
||||
});
|
||||
if (touches.length === 1) {
|
||||
const getPoint = (t) => ({
|
||||
x: t.x || (t.clientX - this.containerRect.left),
|
||||
y: t.y || (t.clientY - this.containerRect.top)
|
||||
});
|
||||
|
||||
const currentPoint = getPoint(touches[0]);
|
||||
const currentPoint = getPoint(touches[0]);
|
||||
|
||||
// 第一次触摸
|
||||
if (!startPoint) {
|
||||
startPoint = currentPoint;
|
||||
startTime = Date.now();
|
||||
}
|
||||
if (!startPoint) {
|
||||
startPoint = currentPoint;
|
||||
startTime = Date.now();
|
||||
}
|
||||
|
||||
// 计算移动距离
|
||||
const dx = currentPoint.x - startPoint.x;
|
||||
const dy = currentPoint.y - startPoint.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
const dx = currentPoint.x - startPoint.x;
|
||||
const dy = currentPoint.y - startPoint.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
// 如果是点击(移动距离小于阈值且时间短)
|
||||
if (isClick && distance < 5 && Date.now() - startTime < 200) {
|
||||
return; // 不执行移动操作
|
||||
}
|
||||
// 区分点击和拖拽
|
||||
if (isClick && distance < 5 && Date.now() - startTime < 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 标记为非点击操作
|
||||
isClick = false;
|
||||
isClick = false;
|
||||
|
||||
// 执行移动操作
|
||||
if (lastPoint) {
|
||||
const moveDx = currentPoint.x - lastPoint.x;
|
||||
const moveDy = currentPoint.y - lastPoint.y;
|
||||
if (lastPoint) {
|
||||
const moveDx = currentPoint.x - lastPoint.x;
|
||||
const moveDy = currentPoint.y - lastPoint.y;
|
||||
|
||||
this.transformMatrix.tx += moveDx;
|
||||
this.transformMatrix.ty += moveDy;
|
||||
}
|
||||
this.transformMatrix.tx += moveDx;
|
||||
this.transformMatrix.ty += moveDy;
|
||||
}
|
||||
|
||||
lastPoint = currentPoint;
|
||||
} else if (touches.length > 1) {
|
||||
this._handlePinch(touches);
|
||||
}
|
||||
lastPoint = currentPoint;
|
||||
} else if (touches.length > 1) {
|
||||
this._handlePinch(touches);
|
||||
}
|
||||
|
||||
// 重置状态
|
||||
if (event.type === 'touchend' || event.type === 'touchcancel') {
|
||||
isClick = true;
|
||||
startPoint = null;
|
||||
startTime = null;
|
||||
lastPoint = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 在触摸结束时重置状态
|
||||
if (event.type === 'touchend' || event.type === 'touchcancel') {
|
||||
isClick = true;
|
||||
startPoint = null;
|
||||
startTime = null;
|
||||
lastPoint = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
setupGestures() {
|
||||
// 平移手势
|
||||
|
@ -27,7 +27,8 @@ export default {
|
||||
})
|
||||
},
|
||||
areaData:{},
|
||||
seatData:{}
|
||||
seatData:{},
|
||||
selectedCodes:{}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -37,10 +38,17 @@ export default {
|
||||
canvasDisplayWidth: 800, // 默认显示尺寸
|
||||
canvasDisplayHeight: 600,
|
||||
canvasActualWidth: 800, // 实际像素尺寸
|
||||
canvasActualHeight: 600
|
||||
canvasActualHeight: 600,
|
||||
nowSelectedCodes:this.selectedCodes
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
selectedCodes:{
|
||||
handler(newVal) {
|
||||
this.nowSelectedCodes = newVal
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
imgUrl: {
|
||||
handler(newUrl) {
|
||||
if (newUrl) this.loadImage(newUrl);
|
||||
@ -83,6 +91,13 @@ export default {
|
||||
this.initCanvas();
|
||||
},
|
||||
methods: {
|
||||
|
||||
invertPoint(x, y) {
|
||||
// 注意:直接使用矩阵的逆转换,不需要除以dpr
|
||||
const inverted = this.matrix.invertPoint(x, y);
|
||||
return inverted;
|
||||
},
|
||||
|
||||
// 添加点击检测方法
|
||||
checkHitArea(x, y) {
|
||||
if (!this.areaData) return null;
|
||||
@ -302,26 +317,62 @@ export default {
|
||||
});
|
||||
},
|
||||
drawSeats() {
|
||||
// 获取当前缩放比例
|
||||
const scale = Math.sqrt(this.matrix.a * this.matrix.a + this.matrix.b * this.matrix.b);
|
||||
this.ctx.save();
|
||||
|
||||
this.seatData.forEach(seat => {
|
||||
// 使用原始坐标(变换矩阵会自动应用)
|
||||
const x = seat.x;
|
||||
const y = seat.y;
|
||||
// 应用变换矩阵
|
||||
const { a, b, c, d, tx, ty } = this.matrix;
|
||||
this.ctx.setTransform(a, b, c, d, tx, ty);
|
||||
|
||||
this.ctx.beginPath();
|
||||
// 根据缩放调整座位大小
|
||||
const radius = 8 / scale;
|
||||
this.ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
// 获取当前缩放比例
|
||||
const scale = Math.sqrt(a * a + b * b);
|
||||
|
||||
this.ctx.fillStyle = seat.status === 1 ? '#4cd964' : '#dd524d';
|
||||
this.ctx.fill();
|
||||
this.seatData.forEach(seat => {
|
||||
const x = seat.x;
|
||||
const y = seat.y;
|
||||
|
||||
// 仅在缩放足够大时显示文字
|
||||
// 根据缩放调整座位大小
|
||||
const radius = 8 / scale;
|
||||
|
||||
});
|
||||
console.log(this.nowSelectedCodes,'nowSelectedCodesnowSelectedCodesnowSelectedCodes')
|
||||
// 修改1:为选中座位添加特殊样式
|
||||
if (this.nowSelectedCodes.has(seat.code) && seat.status === 1) {
|
||||
// 1. 绘制金色边框
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(x, y, radius + 1, 0, Math.PI * 2);
|
||||
this.ctx.strokeStyle = '#FFD700'; // 金色
|
||||
this.ctx.lineWidth = 2 / scale;
|
||||
this.ctx.stroke();
|
||||
|
||||
// 2. 绘制半透明金色背景
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
this.ctx.fillStyle = 'rgba(255, 215, 0, 0.3)';
|
||||
this.ctx.fill();
|
||||
|
||||
// 3. 绘制白色对勾(缩小版)
|
||||
this.ctx.strokeStyle = '#fff';
|
||||
this.ctx.lineWidth = 1 / scale;
|
||||
this.ctx.lineCap = 'round';
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x - 2.5, y);
|
||||
this.ctx.lineTo(x - 0.5, y + 1.5);
|
||||
this.ctx.lineTo(x + 2.5, y - 2);
|
||||
this.ctx.stroke();
|
||||
} else {
|
||||
// 普通座位的绘制保持不变
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
this.ctx.fillStyle = seat.status === 1 ? '#4cd964' : '#dd524d';
|
||||
this.ctx.fill();
|
||||
}
|
||||
|
||||
// 仅在缩放足够大时显示文字
|
||||
|
||||
});
|
||||
|
||||
this.ctx.restore();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
@ -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
@ -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;"}
|
@ -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_8j0jyd";
|
||||
const id = "mp-weixin_3NWJxu";
|
||||
const lazy = typeof swan !== "undefined";
|
||||
let restoreError = lazy ? () => {
|
||||
} : initOnError();
|
||||
|
@ -23,8 +23,10 @@ const _sfc_main = {
|
||||
currentView: "area",
|
||||
seatPositions: [],
|
||||
// 座位数据
|
||||
selectedArea: null
|
||||
selectedArea: null,
|
||||
// 当前选中分区
|
||||
selectedCodes: /* @__PURE__ */ new Set()
|
||||
// 存储选中的座位code
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
@ -42,8 +44,10 @@ const _sfc_main = {
|
||||
const dpr = this.$refs.canvasRef.dpr || 1;
|
||||
const x = (e.detail.x - this.containerRect.left) * dpr;
|
||||
const y = (e.detail.y - this.containerRect.top) * dpr;
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:89", "handleCanvasClick", x, y);
|
||||
if (this.currentView === "area") {
|
||||
const hitArea = this.$refs.canvasRef.checkHitArea(x, y);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:92", "handleCanvasClick", hitArea);
|
||||
if (hitArea) {
|
||||
common_vendor.index.showModal({
|
||||
title: "请确认",
|
||||
@ -55,17 +59,34 @@ const _sfc_main = {
|
||||
this.currentView = "seat";
|
||||
this.loadSeatData(hitArea.areacode);
|
||||
}
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:102", res, "showModa-- success");
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (this.currentView === "seat") {
|
||||
const hitSeat = this.$refs.canvasRef.checkSeatHit(x, y);
|
||||
if (hitSeat) {
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:109", "选中座位:", hitSeat);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:111", "选中座位:", hitSeat);
|
||||
this.toggleSeatSelection(hitSeat);
|
||||
}
|
||||
}
|
||||
},
|
||||
toggleSeatSelection(seat) {
|
||||
if (seat.status !== 1)
|
||||
return;
|
||||
if (this.selectedCodes.has(seat.code)) {
|
||||
this.selectedCodes.delete(seat.code);
|
||||
} else {
|
||||
if (this.selectedCodes.size < 4) {
|
||||
this.selectedCodes.add(seat.code);
|
||||
} else {
|
||||
common_vendor.index.showToast({
|
||||
title: "最多只能选择4个座位",
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
}
|
||||
this.$refs.canvasRef.redraw();
|
||||
},
|
||||
async getContainerPosition() {
|
||||
let retryCount = 0;
|
||||
const maxRetries = 3;
|
||||
@ -87,7 +108,7 @@ const _sfc_main = {
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:140", "获取容器位置失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:162", "获取容器位置失败:", e);
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, 100));
|
||||
retryCount++;
|
||||
@ -98,59 +119,75 @@ const _sfc_main = {
|
||||
this.gestureHandler = new pages_index_gestureHandler.GestureHandler(this, this.transformMatrix, {
|
||||
container: this.containerRect
|
||||
});
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:176", "initGestureHandler", this.gestureHandler);
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:155", "手势处理器初始化失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:178", "手势处理器初始化失败:", e);
|
||||
this.gestureHandler = {
|
||||
catchEvent: (event) => {
|
||||
if (event.touches.length > 0) {
|
||||
this.gestureStatus = "降级模式";
|
||||
this.touchPoints = event.touches.length;
|
||||
if (event.type === "touchmove") {
|
||||
const firstTouch = event.touches[0];
|
||||
const x = firstTouch.clientX - this.containerRect.left;
|
||||
const y = firstTouch.clientY - this.containerRect.top;
|
||||
this.transformMatrix.tx = x;
|
||||
this.transformMatrix.ty = y;
|
||||
this.updateCanvas();
|
||||
}
|
||||
}
|
||||
catchEvent: this.createGestureFallback(),
|
||||
setScale: (scale) => {
|
||||
this.transformMatrix.scale(scale, scale, this.canvasWidth / 2, this.canvasHeight / 2);
|
||||
this.updateCanvas();
|
||||
},
|
||||
reset: () => {
|
||||
this.transformMatrix.reset();
|
||||
this.updateCanvas();
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
// 事件处理
|
||||
async handleTouchEvent(event) {
|
||||
if (!this.gestureHandler || !this.containerRect) {
|
||||
await this.getContainerPosition();
|
||||
this.initGestureHandler();
|
||||
if (event.type === "touchend" || event.type === "touchcancel") {
|
||||
this.gestureStatus = "结束";
|
||||
this.updateCanvas();
|
||||
return;
|
||||
createGestureFallback() {
|
||||
let isClick = true;
|
||||
let startPoint = null;
|
||||
let startTime = null;
|
||||
let lastPoint = null;
|
||||
return (event) => {
|
||||
const touches = event.touches || [];
|
||||
if (touches.length === 1) {
|
||||
const getPoint = (t) => ({
|
||||
x: t.clientX - this.containerRect.left,
|
||||
y: t.clientY - this.containerRect.top
|
||||
});
|
||||
const currentPoint = getPoint(touches[0]);
|
||||
if (!startPoint) {
|
||||
startPoint = currentPoint;
|
||||
startTime = Date.now();
|
||||
}
|
||||
const dx = currentPoint.x - startPoint.x;
|
||||
const dy = currentPoint.y - startPoint.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
if (isClick && distance < 5 && Date.now() - startTime < 200) {
|
||||
return;
|
||||
}
|
||||
isClick = false;
|
||||
if (lastPoint) {
|
||||
const moveDx = currentPoint.x - lastPoint.x;
|
||||
const moveDy = currentPoint.y - lastPoint.y;
|
||||
this.transformMatrix.tx += moveDx;
|
||||
this.transformMatrix.ty += moveDy;
|
||||
}
|
||||
lastPoint = currentPoint;
|
||||
}
|
||||
if (event.type === "touchend" || event.type === "touchcancel") {
|
||||
isClick = true;
|
||||
startPoint = null;
|
||||
startTime = null;
|
||||
lastPoint = null;
|
||||
}
|
||||
}
|
||||
const currentTime = Date.now();
|
||||
this.touchPoints = event.touches.length;
|
||||
const correctedTouches = Array.from(event.touches).map((touch) => {
|
||||
return {
|
||||
...touch,
|
||||
x: touch.clientX - this.containerRect.left,
|
||||
y: touch.clientY - this.containerRect.top
|
||||
};
|
||||
});
|
||||
const correctedEvent = {
|
||||
...event,
|
||||
touches: correctedTouches,
|
||||
changedTouches: correctedTouches
|
||||
};
|
||||
this.gestureHandler.catchEvent(correctedEvent);
|
||||
},
|
||||
async handleTouchEvent(event) {
|
||||
var _a;
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:251", event, "handleTouchEvent");
|
||||
this.touchPoints = event.touches.length;
|
||||
if (event.type === "touchstart") {
|
||||
this.gestureStatus = event.touches.length > 1 ? "双指开始" : "单指开始";
|
||||
} else if (event.type === "touchmove") {
|
||||
this.gestureStatus = event.touches.length > 1 ? "双指缩放/移动" : "单指移动";
|
||||
} else {
|
||||
this.gestureStatus = "结束";
|
||||
}
|
||||
(_a = this.gestureHandler) == null ? void 0 : _a.catchEvent(event);
|
||||
if (event.type === "touchend" || event.type === "touchcancel") {
|
||||
this.gestureStatus = "结束";
|
||||
this.updateCanvas();
|
||||
}
|
||||
const currentTime = Date.now();
|
||||
if (currentTime - this.lastGestureTime > 50) {
|
||||
this.lastGestureTime = currentTime;
|
||||
this.updateCanvas();
|
||||
@ -491,7 +528,7 @@ const _sfc_main = {
|
||||
};
|
||||
this.seatAreas = response.data;
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:574", "加载区域数据失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:618", "加载区域数据失败:", e);
|
||||
}
|
||||
},
|
||||
async loadSeatData(areaCode) {
|
||||
@ -512,11 +549,16 @@ const _sfc_main = {
|
||||
});
|
||||
this.transformMatrix = new pages_index_transformMatrix.TransformMatrix();
|
||||
this.$nextTick(() => {
|
||||
if (!this.gestureHandler) {
|
||||
this.initGestureHandler();
|
||||
}
|
||||
if (this.seatPositions.length > 0) {
|
||||
const minX = Math.min(...this.seatPositions.map((s) => s.x));
|
||||
const maxX = Math.max(...this.seatPositions.map((s) => s.x));
|
||||
const minY = Math.min(...this.seatPositions.map((s) => s.y));
|
||||
const maxY = Math.max(...this.seatPositions.map((s) => s.y));
|
||||
const xs = this.seatPositions.map((s) => s.x);
|
||||
const ys = this.seatPositions.map((s) => s.y);
|
||||
const minX = Math.min(...xs);
|
||||
const maxX = Math.max(...xs);
|
||||
const minY = Math.min(...ys);
|
||||
const maxY = Math.max(...ys);
|
||||
const centerX = (minX + maxX) / 2;
|
||||
const centerY = (minY + maxY) / 2;
|
||||
const widthRatio = this.canvasWidth / (maxX - minX + 100);
|
||||
@ -525,7 +567,7 @@ const _sfc_main = {
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:624", "加载座位数据失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:676", "加载座位数据失败:", e);
|
||||
common_vendor.index.showToast({ title: "加载座位失败", icon: "none" });
|
||||
}
|
||||
}
|
||||
@ -549,7 +591,8 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
matrix: $data.transformMatrix,
|
||||
imgUrl: "https://assets.tech.troyrc.com/sx25/images/events/XBDT.jpg",
|
||||
areaData: $data.currentView === "area" ? $data.seatAreas : [],
|
||||
seatData: $data.currentView === "seat" ? $data.seatPositions : []
|
||||
seatData: $data.currentView === "seat" ? $data.seatPositions : [],
|
||||
selectedCodes: $data.selectedCodes
|
||||
}),
|
||||
h: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)),
|
||||
i: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)),
|
||||
|
@ -6,9 +6,10 @@ class GestureHandler {
|
||||
this.containerRect = container;
|
||||
this.panThreshold = 5;
|
||||
this.panStarted = false;
|
||||
this.context = context;
|
||||
this.isMiniProgram = typeof common_vendor.wx$1 !== "undefined" || typeof common_vendor.index !== "undefined";
|
||||
if (this.isMiniProgram) {
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:13", "小程序环境,使用降级手势处理器");
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:14", "小程序环境,使用降级手势处理器");
|
||||
this.catchEvent = this.createSimpleGestureHandler();
|
||||
return;
|
||||
}
|
||||
@ -35,17 +36,16 @@ class GestureHandler {
|
||||
"../../common/vendor.js".then((n) => n.index_es).then((AnyTouch) => {
|
||||
this.at = new AnyTouch.default(atOptions);
|
||||
this.setupGestures();
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:44", "AnyTouch手势处理器已初始化");
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:45", "AnyTouch手势处理器已初始化");
|
||||
}).catch((e) => {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:46", "AnyTouch加载失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:47", "AnyTouch加载失败:", e);
|
||||
this.catchEvent = this.createSimpleGestureHandler();
|
||||
});
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:50", "AnyTouch初始化失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:51", "AnyTouch初始化失败:", e);
|
||||
this.catchEvent = this.createSimpleGestureHandler();
|
||||
}
|
||||
}
|
||||
// 创建小程序专用的简化手势处理器
|
||||
createSimpleGestureHandler() {
|
||||
let isClick = true;
|
||||
let startPoint = null;
|
||||
@ -135,7 +135,7 @@ class GestureHandler {
|
||||
this.catchEvent(event);
|
||||
}
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:178", "手势处理错误:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:176", "手势处理错误:", e);
|
||||
}
|
||||
}
|
||||
// 基础平移手势处理
|
||||
|
@ -21,7 +21,8 @@ const _sfc_main = {
|
||||
})
|
||||
},
|
||||
areaData: {},
|
||||
seatData: {}
|
||||
seatData: {},
|
||||
selectedCodes: {}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -33,10 +34,17 @@ const _sfc_main = {
|
||||
canvasDisplayHeight: 600,
|
||||
canvasActualWidth: 800,
|
||||
// 实际像素尺寸
|
||||
canvasActualHeight: 600
|
||||
canvasActualHeight: 600,
|
||||
nowSelectedCodes: this.selectedCodes
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
selectedCodes: {
|
||||
handler(newVal) {
|
||||
this.nowSelectedCodes = newVal;
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
imgUrl: {
|
||||
handler(newUrl) {
|
||||
if (newUrl)
|
||||
@ -81,12 +89,16 @@ const _sfc_main = {
|
||||
this.initCanvas();
|
||||
},
|
||||
methods: {
|
||||
invertPoint(x, y) {
|
||||
const inverted = this.matrix.invertPoint(x, y);
|
||||
return inverted;
|
||||
},
|
||||
// 添加点击检测方法
|
||||
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);
|
||||
common_vendor.index.__f__("log", "at pages/index/transform-canvas.vue:107", "checkHitArea", inverted);
|
||||
for (const area of this.areaData) {
|
||||
if (this.pointInPolygon(inverted.x, inverted.y, area.polygon)) {
|
||||
return area;
|
||||
@ -173,7 +185,7 @@ const _sfc_main = {
|
||||
});
|
||||
this.redraw();
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:223", "图片加载失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/transform-canvas.vue:238", "图片加载失败:", e);
|
||||
this.image = null;
|
||||
}
|
||||
},
|
||||
@ -242,16 +254,40 @@ const _sfc_main = {
|
||||
});
|
||||
},
|
||||
drawSeats() {
|
||||
const scale = Math.sqrt(this.matrix.a * this.matrix.a + this.matrix.b * this.matrix.b);
|
||||
this.ctx.save();
|
||||
const { a, b, c, d, tx, ty } = this.matrix;
|
||||
this.ctx.setTransform(a, b, c, d, tx, ty);
|
||||
const scale = Math.sqrt(a * a + b * 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();
|
||||
if (this.nowSelectedCodes.has(seat.code) && seat.status === 1) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(x, y, radius + 1, 0, Math.PI * 2);
|
||||
this.ctx.strokeStyle = "#FFD700";
|
||||
this.ctx.lineWidth = 2 / scale;
|
||||
this.ctx.stroke();
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
this.ctx.fillStyle = "rgba(255, 215, 0, 0.3)";
|
||||
this.ctx.fill();
|
||||
this.ctx.strokeStyle = "#fff";
|
||||
this.ctx.lineWidth = 1 / scale;
|
||||
this.ctx.lineCap = "round";
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x - 2.5, y);
|
||||
this.ctx.lineTo(x - 0.5, y + 1.5);
|
||||
this.ctx.lineTo(x + 2.5, y - 2);
|
||||
this.ctx.stroke();
|
||||
} else {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
this.ctx.fillStyle = seat.status === 1 ? "#4cd964" : "#dd524d";
|
||||
this.ctx.fill();
|
||||
}
|
||||
});
|
||||
this.ctx.restore();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user