test:测试手势js、矩阵js 展示没问题
This commit is contained in:
parent
0c82be5f58
commit
94e79c4b77
@ -25,7 +25,6 @@
|
||||
<button @click="resetCanvas">重置</button>
|
||||
<button @click="zoomIn">放大</button>
|
||||
<button @click="zoomOut">缩小</button>
|
||||
<button @click="logMatrix">调试</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@ -69,30 +68,35 @@ export default {
|
||||
methods: {
|
||||
// 独立的手势初始化方法
|
||||
initGestureHandler() {
|
||||
try {
|
||||
this.gestureHandler = new GestureHandler(this, this.transformMatrix, {
|
||||
container: this.containerRect
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('手势处理器初始化失败:', e);
|
||||
// 创建降级方案
|
||||
this.gestureHandler = {
|
||||
catchEvent: (event) => {
|
||||
// 基本手势处理
|
||||
const touches = event.touches || [];
|
||||
if (touches.length > 0) {
|
||||
const point = touches[0];
|
||||
const x = point.clientX - this.containerRect.left;
|
||||
const y = point.clientY - this.containerRect.top;
|
||||
|
||||
// 简单移动逻辑
|
||||
this.transformMatrix.tx = x - 50;
|
||||
this.transformMatrix.ty = y - 50;
|
||||
this.updateCanvas();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
const firstTouch = event.touches[0];
|
||||
const x = firstTouch.clientX - this.containerRect.left;
|
||||
const y = firstTouch.clientY - this.containerRect.top;
|
||||
|
||||
// 仅更新调试信息显示
|
||||
this.gestureStatus = "降级模式: 单指拖动";
|
||||
this.touchPoints = event.touches.length;
|
||||
|
||||
// 简单变换
|
||||
if (event.type === 'touchmove') {
|
||||
this.transformMatrix.tx = x;
|
||||
this.transformMatrix.ty = y;
|
||||
this.updateCanvas();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async getContainerPosition() {
|
||||
@ -130,18 +134,35 @@ export default {
|
||||
|
||||
console.error(`容器位置获取失败,已重试${maxRetries}次`);
|
||||
},
|
||||
// 事件处理(完整修复)
|
||||
// 事件处理
|
||||
async handleTouchEvent(event) {
|
||||
// 修复点1:确保处理器就绪的防护代码
|
||||
|
||||
if (!this.gestureHandler || !this.containerRect) {
|
||||
console.warn('手势处理器未就绪,尝试重新初始化...');
|
||||
await this.getContainerPosition();
|
||||
this.initGestureHandler();
|
||||
|
||||
if (event.type === 'touchend' || event.type === 'touchcancel') {
|
||||
this.lastPoint = null;
|
||||
this.lastPoints = null;
|
||||
this.gestureStatus = '结束';
|
||||
|
||||
// 更新一次画面
|
||||
this.updateCanvas();
|
||||
return;
|
||||
}
|
||||
// 重新处理当前事件
|
||||
if (this.gestureHandler) {
|
||||
return this.handleTouchEvent(event);
|
||||
}
|
||||
// 如果是简单处理器,使用下面优化的基础处理方法
|
||||
if (!this.at) {
|
||||
// 使用优化后的基础处理方法
|
||||
if (correctedEvent.touches.length === 1) {
|
||||
this.handlePan(correctedEvent.touches[0]);
|
||||
} else if (correctedEvent.touches.length > 1) {
|
||||
this.handlePinch(correctedEvent.touches);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -230,14 +251,6 @@ export default {
|
||||
this.updateCanvas();
|
||||
},
|
||||
|
||||
// 调试输出
|
||||
logMatrix() {
|
||||
console.log('当前变换矩阵:', this.transformMatrix.toArray());
|
||||
console.log('容器位置:', this.containerRect);
|
||||
if (this.$refs.canvasRef) {
|
||||
this.$refs.canvasRef.drawDebugGrid();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -4,6 +4,8 @@ class GestureHandler {
|
||||
constructor(context, transformMatrix, { container }) {
|
||||
this.transformMatrix = transformMatrix;
|
||||
this.containerRect = container;
|
||||
this.panThreshold = 5; // 移动5像素以上才认为是拖动
|
||||
this.panStarted = false;
|
||||
|
||||
// 小程序环境兼容处理
|
||||
const atOptions = {
|
||||
@ -49,10 +51,10 @@ class GestureHandler {
|
||||
|
||||
if (touches.length === 1) {
|
||||
// 单指移动
|
||||
this.handlePan(touches[0]);
|
||||
this._handlePan(touches[0]);
|
||||
} else if (touches.length > 1) {
|
||||
// 双指缩放
|
||||
this.handlePinch(touches);
|
||||
this._handlePinch(touches);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -63,9 +65,23 @@ class GestureHandler {
|
||||
this.at.on('pan', (event) => {
|
||||
if (event.type === 'panstart') {
|
||||
console.log('panstart', event);
|
||||
// 重置移动开始状态
|
||||
this.panStarted = false;
|
||||
}
|
||||
else if (event.type === 'panmove') {
|
||||
// 关键修复:基于当前缩放比例修正移动量
|
||||
// 检查是否超过阈值
|
||||
const distance = Math.sqrt(event.deltaX**2 + event.deltaY**2);
|
||||
|
||||
if (!this.panStarted && distance < this.panThreshold) {
|
||||
return; // 小于阈值不处理
|
||||
}
|
||||
|
||||
if (!this.panStarted) {
|
||||
console.log('拖动手势开始');
|
||||
this.panStarted = true;
|
||||
}
|
||||
|
||||
// 基于当前缩放比例修正移动量
|
||||
const currentScale = Math.sqrt(
|
||||
this.transformMatrix.a * this.transformMatrix.a +
|
||||
this.transformMatrix.b * this.transformMatrix.b
|
||||
@ -75,9 +91,12 @@ class GestureHandler {
|
||||
const dx = event.deltaX / currentScale;
|
||||
const dy = event.deltaY / currentScale;
|
||||
|
||||
|
||||
console.log(`平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`);
|
||||
|
||||
this.transformMatrix.translate(dx, dy);
|
||||
} else if (event.type === 'panend') {
|
||||
this.panStarted = false;
|
||||
}
|
||||
});
|
||||
|
||||
@ -114,77 +133,92 @@ class GestureHandler {
|
||||
}
|
||||
|
||||
|
||||
catchEvent(event) {
|
||||
try {
|
||||
if (this.at) {
|
||||
this.at.run(event);
|
||||
} else if (this.handleGesture) {
|
||||
this.handleGesture.run(event);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('手势处理错误:', e);
|
||||
// 降级处理
|
||||
const touches = event.touches || [];
|
||||
if (touches.length > 0) {
|
||||
this.handlePan(touches[0]);
|
||||
// 公共接口保持不变
|
||||
catchEvent(event) {
|
||||
try {
|
||||
if (this.at) {
|
||||
this.at.run(event);
|
||||
} else {
|
||||
// 内部处理降级方案
|
||||
const touches = event.touches || [];
|
||||
const eventType = event.type;
|
||||
|
||||
// 在事件开始时重置状态
|
||||
if (eventType === 'touchstart') {
|
||||
this.lastPoint = null;
|
||||
this.lastPoints = null;
|
||||
this.lastDistance = null;
|
||||
}
|
||||
|
||||
// 处理不同数量的手指
|
||||
if (touches.length === 1) {
|
||||
this._handlePan(touches[0]);
|
||||
} else if (touches.length > 1) {
|
||||
this._handlePinch(touches);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('手势处理错误:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 基础平移手势处理
|
||||
handlePan(touch) {
|
||||
if (this.lastPoint) {
|
||||
const dx = touch.clientX - this.lastPoint.x;
|
||||
const dy = touch.clientY - this.lastPoint.y;
|
||||
|
||||
// 根据当前缩放比例修正移动量
|
||||
const currentScale = Math.sqrt(
|
||||
this.transformMatrix.a * this.transformMatrix.a +
|
||||
this.transformMatrix.b * this.transformMatrix.b
|
||||
);
|
||||
|
||||
const correctedDx = dx / currentScale;
|
||||
const correctedDy = dy / currentScale;
|
||||
|
||||
this.transformMatrix.translate(correctedDx, correctedDy);
|
||||
}
|
||||
this.lastPoint = {x: touch.clientX, y: touch.clientY};
|
||||
_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};
|
||||
}
|
||||
|
||||
// 基础缩放手势处理
|
||||
handlePinch(touches) {
|
||||
_handlePinch(touches) {
|
||||
const point1 = touches[0];
|
||||
const point2 = touches[1];
|
||||
|
||||
if (this.lastPoints) {
|
||||
// 计算当前距离
|
||||
const currentDistance = Math.sqrt(
|
||||
Math.pow(point2.clientX - point1.clientX, 2) +
|
||||
Math.pow(point2.clientY - point1.clientY, 2)
|
||||
);
|
||||
|
||||
// 上次距离
|
||||
const prevDistance = Math.sqrt(
|
||||
Math.pow(this.lastPoints[1].x - this.lastPoints[0].x, 2) +
|
||||
Math.pow(this.lastPoints[1].y - this.lastPoints[0].y, 2)
|
||||
);
|
||||
|
||||
// 缩放比例
|
||||
if (prevDistance > 0) {
|
||||
const scaleChange = currentDistance / prevDistance;
|
||||
|
||||
// 计算中心点
|
||||
const centerX = (point1.clientX + point2.clientX) / 2 - this.containerRect.left;
|
||||
const centerY = (point1.clientY + point2.clientY) / 2 - this.containerRect.top;
|
||||
|
||||
this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);
|
||||
}
|
||||
}
|
||||
|
||||
this.lastPoints = [
|
||||
{x: point1.clientX, y: point1.clientY},
|
||||
{x: point2.clientX, y: point2.clientY}
|
||||
];
|
||||
const point2 = touches[1];
|
||||
|
||||
// 获取容器坐标系坐标
|
||||
const getPoint = (touch) => ({
|
||||
x: touch.x || (touch.clientX - this.containerRect.left),
|
||||
y: touch.y || (touch.clientY - this.containerRect.top)
|
||||
});
|
||||
|
||||
const currentPoints = [getPoint(point1), getPoint(point2)];
|
||||
|
||||
if (this.lastPoints) {
|
||||
// 计算当前距离 (容器坐标系)
|
||||
const currentDistance = Math.sqrt(
|
||||
Math.pow(currentPoints[1].x - currentPoints[0].x, 2) +
|
||||
Math.pow(currentPoints[1].y - currentPoints[0].y, 2)
|
||||
);
|
||||
|
||||
// 上次距离 (容器坐标系)
|
||||
const prevDistance = Math.sqrt(
|
||||
Math.pow(this.lastPoints[1].x - this.lastPoints[0].x, 2) +
|
||||
Math.pow(this.lastPoints[1].y - this.lastPoints[0].y, 2)
|
||||
);
|
||||
|
||||
// 缩放比例
|
||||
if (prevDistance > 0 && currentDistance > 0) {
|
||||
const scaleChange = currentDistance / prevDistance;
|
||||
|
||||
// 计算中心点 (容器坐标系)
|
||||
const centerX = (currentPoints[0].x + currentPoints[1].x) / 2;
|
||||
const centerY = (currentPoints[0].y + currentPoints[1].y) / 2;
|
||||
|
||||
this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);
|
||||
}
|
||||
}
|
||||
|
||||
// 存储当前点
|
||||
this.lastPoints = currentPoints;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,57 +52,57 @@ export default {
|
||||
},
|
||||
|
||||
// 调试网格
|
||||
drawDebugGrid() {
|
||||
if (!this.ctx) return;
|
||||
// drawDebugGrid() {
|
||||
// if (!this.ctx) return;
|
||||
|
||||
const pixelRatio = uni.getSystemInfoSync().pixelRatio;
|
||||
const width = this.canvasWidth * pixelRatio;
|
||||
const height = this.canvasHeight * pixelRatio;
|
||||
// const pixelRatio = uni.getSystemInfoSync().pixelRatio;
|
||||
// const width = this.canvasWidth * pixelRatio;
|
||||
// const height = this.canvasHeight * pixelRatio;
|
||||
|
||||
// 保存当前状态
|
||||
this.ctx.save();
|
||||
// // 保存当前状态
|
||||
// this.ctx.save();
|
||||
|
||||
// 重置变换
|
||||
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
// // 重置变换
|
||||
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
|
||||
// 绘制网格
|
||||
this.ctx.strokeStyle = 'rgba(200, 200, 200, 0.3)';
|
||||
this.ctx.lineWidth = 1;
|
||||
// // 绘制网格
|
||||
// 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 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();
|
||||
}
|
||||
// // 纵向线
|
||||
// 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.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.beginPath();
|
||||
// this.ctx.moveTo(0, 0);
|
||||
// this.ctx.lineTo(0, height);
|
||||
// this.ctx.stroke();
|
||||
|
||||
// 恢复之前的状态
|
||||
this.ctx.restore();
|
||||
// // 恢复之前的状态
|
||||
// this.ctx.restore();
|
||||
|
||||
this.ctx.draw();
|
||||
},
|
||||
// this.ctx.draw();
|
||||
// },
|
||||
|
||||
// 绘制主内容
|
||||
draw() {
|
||||
|
@ -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.205";
|
||||
const port = "8090";
|
||||
const id = "mp-weixin_j4oiF-";
|
||||
const id = "mp-weixin_aMdMwA";
|
||||
const lazy = typeof swan !== "undefined";
|
||||
let restoreError = lazy ? () => {
|
||||
} : initOnError();
|
||||
|
@ -35,17 +35,20 @@ const _sfc_main = {
|
||||
container: this.containerRect
|
||||
});
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:77", "手势处理器初始化失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:76", "手势处理器初始化失败:", e);
|
||||
this.gestureHandler = {
|
||||
catchEvent: (event) => {
|
||||
const touches = event.touches || [];
|
||||
if (touches.length > 0) {
|
||||
const point = touches[0];
|
||||
const x = point.clientX - this.containerRect.left;
|
||||
const y = point.clientY - this.containerRect.top;
|
||||
this.transformMatrix.tx = x - 50;
|
||||
this.transformMatrix.ty = y - 50;
|
||||
this.updateCanvas();
|
||||
if (event.touches.length > 0) {
|
||||
const firstTouch = event.touches[0];
|
||||
const x = firstTouch.clientX - this.containerRect.left;
|
||||
const y = firstTouch.clientY - this.containerRect.top;
|
||||
this.gestureStatus = "降级模式: 单指拖动";
|
||||
this.touchPoints = event.touches.length;
|
||||
if (event.type === "touchmove") {
|
||||
this.transformMatrix.tx = x;
|
||||
this.transformMatrix.ty = y;
|
||||
this.updateCanvas();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -69,26 +72,40 @@ const _sfc_main = {
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
};
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:119", "成功获取容器位置:", this.containerRect);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:123", "成功获取容器位置:", this.containerRect);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:123", "获取容器位置失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:127", "获取容器位置失败:", e);
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, 100));
|
||||
retryCount++;
|
||||
}
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:131", `容器位置获取失败,已重试${maxRetries}次`);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-canvas-page.vue:135", `容器位置获取失败,已重试${maxRetries}次`);
|
||||
},
|
||||
// 事件处理(完整修复)
|
||||
// 事件处理
|
||||
async handleTouchEvent(event) {
|
||||
if (!this.gestureHandler || !this.containerRect) {
|
||||
common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:137", "手势处理器未就绪,尝试重新初始化...");
|
||||
common_vendor.index.__f__("warn", "at pages/index/gesture-canvas-page.vue:141", "手势处理器未就绪,尝试重新初始化...");
|
||||
await this.getContainerPosition();
|
||||
this.initGestureHandler();
|
||||
if (event.type === "touchend" || event.type === "touchcancel") {
|
||||
this.lastPoint = null;
|
||||
this.lastPoints = null;
|
||||
this.gestureStatus = "结束";
|
||||
this.updateCanvas();
|
||||
return;
|
||||
}
|
||||
if (this.gestureHandler) {
|
||||
return this.handleTouchEvent(event);
|
||||
}
|
||||
if (!this.at) {
|
||||
if (correctedEvent.touches.length === 1) {
|
||||
this.handlePan(correctedEvent.touches[0]);
|
||||
} else if (correctedEvent.touches.length > 1) {
|
||||
this.handlePinch(correctedEvent.touches);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
const currentTime = Date.now();
|
||||
@ -96,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:160", `原始坐标: (${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,
|
||||
@ -149,14 +166,6 @@ const _sfc_main = {
|
||||
zoomOut() {
|
||||
this.transformMatrix.scale(0.8, 0.8, this.canvasWidth / 2, this.canvasHeight / 2);
|
||||
this.updateCanvas();
|
||||
},
|
||||
// 调试输出
|
||||
logMatrix() {
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:235", "当前变换矩阵:", this.transformMatrix.toArray());
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-canvas-page.vue:236", "容器位置:", this.containerRect);
|
||||
if (this.$refs.canvasRef) {
|
||||
this.$refs.canvasRef.drawDebugGrid();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -183,8 +192,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
k: common_vendor.o((...args) => $options.handleTouchEvent && $options.handleTouchEvent(...args)),
|
||||
l: common_vendor.o((...args) => $options.resetCanvas && $options.resetCanvas(...args)),
|
||||
m: common_vendor.o((...args) => $options.zoomIn && $options.zoomIn(...args)),
|
||||
n: common_vendor.o((...args) => $options.zoomOut && $options.zoomOut(...args)),
|
||||
o: common_vendor.o((...args) => $options.logMatrix && $options.logMatrix(...args))
|
||||
n: common_vendor.o((...args) => $options.zoomOut && $options.zoomOut(...args))
|
||||
};
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-2e633000"]]);
|
||||
|
@ -1 +1 @@
|
||||
<view class="container data-v-2e633000"><view class="gesture-container data-v-2e633000" bindtouchstart="{{h}}" bindtouchmove="{{i}}" bindtouchend="{{j}}" bindtouchcancel="{{k}}"><view class="debug-info data-v-2e633000"><text class="data-v-2e633000">缩放: {{a}} | X: {{b}} | Y: {{c}}</text><text class="data-v-2e633000">手势: {{d}}</text><text class="data-v-2e633000">触点: {{e}}</text></view><transform-canvas wx:if="{{g}}" class="r data-v-2e633000" u-r="canvasRef" u-i="2e633000-0" bind:__l="__l" u-p="{{g}}"/></view><view class="controls data-v-2e633000"><button class="data-v-2e633000" bindtap="{{l}}">重置</button><button class="data-v-2e633000" bindtap="{{m}}">放大</button><button class="data-v-2e633000" bindtap="{{n}}">缩小</button><button class="data-v-2e633000" bindtap="{{o}}">调试</button></view></view>
|
||||
<view class="container data-v-2e633000"><view class="gesture-container data-v-2e633000" bindtouchstart="{{h}}" bindtouchmove="{{i}}" bindtouchend="{{j}}" bindtouchcancel="{{k}}"><view class="debug-info data-v-2e633000"><text class="data-v-2e633000">缩放: {{a}} | X: {{b}} | Y: {{c}}</text><text class="data-v-2e633000">手势: {{d}}</text><text class="data-v-2e633000">触点: {{e}}</text></view><transform-canvas wx:if="{{g}}" class="r data-v-2e633000" u-r="canvasRef" u-i="2e633000-0" bind:__l="__l" u-p="{{g}}"/></view><view class="controls data-v-2e633000"><button class="data-v-2e633000" bindtap="{{l}}">重置</button><button class="data-v-2e633000" bindtap="{{m}}">放大</button><button class="data-v-2e633000" bindtap="{{n}}">缩小</button></view></view>
|
@ -4,6 +4,8 @@ class GestureHandler {
|
||||
constructor(context, transformMatrix, { container }) {
|
||||
this.transformMatrix = transformMatrix;
|
||||
this.containerRect = container;
|
||||
this.panThreshold = 5;
|
||||
this.panStarted = false;
|
||||
const atOptions = {
|
||||
getPoint: (touch) => ({
|
||||
x: touch.clientX - this.containerRect.left,
|
||||
@ -23,14 +25,14 @@ class GestureHandler {
|
||||
try {
|
||||
this.at = new common_vendor.i(atOptions);
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:30", "AnyTouch初始化失败:", e);
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:32", "AnyTouch初始化失败:", e);
|
||||
this.handleGesture = this.createSimpleGestureHandler();
|
||||
}
|
||||
if (this.at) {
|
||||
this.setupGestures();
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:37", "AnyTouch手势处理器已初始化");
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:39", "AnyTouch手势处理器已初始化");
|
||||
} else {
|
||||
common_vendor.index.__f__("warn", "at pages/index/gesture-handler.js:39", "使用简化手势处理器");
|
||||
common_vendor.index.__f__("warn", "at pages/index/gesture-handler.js:41", "使用简化手势处理器");
|
||||
}
|
||||
}
|
||||
// 创建小程序专用的简化手势处理器
|
||||
@ -39,9 +41,9 @@ class GestureHandler {
|
||||
run: (event) => {
|
||||
const touches = event.touches || [];
|
||||
if (touches.length === 1) {
|
||||
this.handlePan(touches[0]);
|
||||
this._handlePan(touches[0]);
|
||||
} else if (touches.length > 1) {
|
||||
this.handlePinch(touches);
|
||||
this._handlePinch(touches);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -49,15 +51,26 @@ class GestureHandler {
|
||||
setupGestures() {
|
||||
this.at.on("pan", (event) => {
|
||||
if (event.type === "panstart") {
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:65", "panstart", event);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:67", "panstart", event);
|
||||
this.panStarted = false;
|
||||
} else if (event.type === "panmove") {
|
||||
const distance = Math.sqrt(event.deltaX ** 2 + event.deltaY ** 2);
|
||||
if (!this.panStarted && distance < this.panThreshold) {
|
||||
return;
|
||||
}
|
||||
if (!this.panStarted) {
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:80", "拖动手势开始");
|
||||
this.panStarted = true;
|
||||
}
|
||||
const currentScale = Math.sqrt(
|
||||
this.transformMatrix.a * this.transformMatrix.a + this.transformMatrix.b * this.transformMatrix.b
|
||||
);
|
||||
const dx = event.deltaX / currentScale;
|
||||
const dy = event.deltaY / currentScale;
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:78", `平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:95", `平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`);
|
||||
this.transformMatrix.translate(dx, dy);
|
||||
} else if (event.type === "panend") {
|
||||
this.panStarted = false;
|
||||
}
|
||||
});
|
||||
this.at.on("pinch", (event) => {
|
||||
@ -68,68 +81,75 @@ class GestureHandler {
|
||||
this.lastScale = event.scale;
|
||||
const centerX = event.center.x;
|
||||
const centerY = event.center.y;
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:98", `缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:117", `缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`);
|
||||
this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);
|
||||
}
|
||||
});
|
||||
this.at.on("tap", (event) => {
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:107", "点击事件", event);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:126", "点击事件", event);
|
||||
});
|
||||
this.at.on("press", (event) => {
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:112", "长按事件", event);
|
||||
common_vendor.index.__f__("log", "at pages/index/gesture-handler.js:131", "长按事件", event);
|
||||
});
|
||||
}
|
||||
// 公共接口保持不变
|
||||
catchEvent(event) {
|
||||
try {
|
||||
if (this.at) {
|
||||
this.at.run(event);
|
||||
} else if (this.handleGesture) {
|
||||
this.handleGesture.run(event);
|
||||
} else {
|
||||
const touches = event.touches || [];
|
||||
const eventType = event.type;
|
||||
if (eventType === "touchstart") {
|
||||
this.lastPoint = null;
|
||||
this.lastPoints = null;
|
||||
this.lastDistance = null;
|
||||
}
|
||||
if (touches.length === 1) {
|
||||
this._handlePan(touches[0]);
|
||||
} else if (touches.length > 1) {
|
||||
this._handlePinch(touches);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:125", "手势处理错误:", e);
|
||||
const touches = event.touches || [];
|
||||
if (touches.length > 0) {
|
||||
this.handlePan(touches[0]);
|
||||
}
|
||||
common_vendor.index.__f__("error", "at pages/index/gesture-handler.js:161", "手势处理错误:", e);
|
||||
}
|
||||
}
|
||||
// 基础平移手势处理
|
||||
handlePan(touch) {
|
||||
_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 = touch.clientX - this.lastPoint.x;
|
||||
const dy = touch.clientY - this.lastPoint.y;
|
||||
const currentScale = Math.sqrt(
|
||||
this.transformMatrix.a * this.transformMatrix.a + this.transformMatrix.b * this.transformMatrix.b
|
||||
);
|
||||
const correctedDx = dx / currentScale;
|
||||
const correctedDy = dy / currentScale;
|
||||
this.transformMatrix.translate(correctedDx, correctedDy);
|
||||
const dx = pointX - this.lastPoint.x;
|
||||
const dy = pointY - this.lastPoint.y;
|
||||
this.transformMatrix.translate(dx, dy);
|
||||
}
|
||||
this.lastPoint = { x: touch.clientX, y: touch.clientY };
|
||||
this.lastPoint = { x: pointX, y: pointY };
|
||||
}
|
||||
// 基础缩放手势处理
|
||||
handlePinch(touches) {
|
||||
_handlePinch(touches) {
|
||||
const point1 = touches[0];
|
||||
const point2 = touches[1];
|
||||
const getPoint = (touch) => ({
|
||||
x: touch.x || touch.clientX - this.containerRect.left,
|
||||
y: touch.y || touch.clientY - this.containerRect.top
|
||||
});
|
||||
const currentPoints = [getPoint(point1), getPoint(point2)];
|
||||
if (this.lastPoints) {
|
||||
const currentDistance = Math.sqrt(
|
||||
Math.pow(point2.clientX - point1.clientX, 2) + Math.pow(point2.clientY - point1.clientY, 2)
|
||||
Math.pow(currentPoints[1].x - currentPoints[0].x, 2) + Math.pow(currentPoints[1].y - currentPoints[0].y, 2)
|
||||
);
|
||||
const prevDistance = Math.sqrt(
|
||||
Math.pow(this.lastPoints[1].x - this.lastPoints[0].x, 2) + Math.pow(this.lastPoints[1].y - this.lastPoints[0].y, 2)
|
||||
);
|
||||
if (prevDistance > 0) {
|
||||
if (prevDistance > 0 && currentDistance > 0) {
|
||||
const scaleChange = currentDistance / prevDistance;
|
||||
const centerX = (point1.clientX + point2.clientX) / 2 - this.containerRect.left;
|
||||
const centerY = (point1.clientY + point2.clientY) / 2 - this.containerRect.top;
|
||||
const centerX = (currentPoints[0].x + currentPoints[1].x) / 2;
|
||||
const centerY = (currentPoints[0].y + currentPoints[1].y) / 2;
|
||||
this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);
|
||||
}
|
||||
}
|
||||
this.lastPoints = [
|
||||
{ x: point1.clientX, y: point1.clientY },
|
||||
{ x: point2.clientX, y: point2.clientY }
|
||||
];
|
||||
this.lastPoints = currentPoints;
|
||||
}
|
||||
}
|
||||
exports.GestureHandler = GestureHandler;
|
||||
|
@ -38,41 +38,47 @@ const _sfc_main = {
|
||||
);
|
||||
},
|
||||
// 调试网格
|
||||
drawDebugGrid() {
|
||||
if (!this.ctx)
|
||||
return;
|
||||
const pixelRatio = common_vendor.index.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();
|
||||
},
|
||||
// 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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user