191 lines
5.4 KiB
JavaScript
191 lines
5.4 KiB
JavaScript
import AnyTouch from 'any-touch'
|
|
|
|
class GestureHandler {
|
|
constructor(context, transformMatrix, { container }) {
|
|
this.transformMatrix = transformMatrix;
|
|
this.containerRect = container;
|
|
|
|
// 小程序环境兼容处理
|
|
const atOptions = {
|
|
getPoint: touch => ({
|
|
x: touch.clientX - this.containerRect.left,
|
|
y: touch.clientY - this.containerRect.top
|
|
}),
|
|
preventDefault: false
|
|
};
|
|
|
|
// 小程序特化处理 - 跳过DOM相关操作
|
|
if (typeof window === 'undefined' || typeof HTMLElement === 'undefined') {
|
|
// 小程序环境下不需要设置DOM属性
|
|
atOptions._element = {
|
|
style: {},
|
|
addEventListener: () => {},
|
|
removeEventListener: () => {}
|
|
};
|
|
}
|
|
|
|
try {
|
|
this.at = new AnyTouch(atOptions);
|
|
} catch (e) {
|
|
console.error('AnyTouch初始化失败:', e);
|
|
// 降级方案:在小程序环境实现基本手势
|
|
this.handleGesture = this.createSimpleGestureHandler();
|
|
}
|
|
|
|
if (this.at) {
|
|
this.setupGestures();
|
|
console.log('AnyTouch手势处理器已初始化');
|
|
} else {
|
|
console.warn('使用简化手势处理器');
|
|
}
|
|
}
|
|
|
|
// 创建小程序专用的简化手势处理器
|
|
createSimpleGestureHandler() {
|
|
return {
|
|
run: (event) => {
|
|
// 小程序环境下的基本手势实现
|
|
const touches = event.touches || [];
|
|
|
|
if (touches.length === 1) {
|
|
// 单指移动
|
|
this.handlePan(touches[0]);
|
|
} else if (touches.length > 1) {
|
|
// 双指缩放
|
|
this.handlePinch(touches);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
setupGestures() {
|
|
// 平移手势 - 修复版本
|
|
this.at.on('pan', (event) => {
|
|
if (event.type === 'panstart') {
|
|
console.log('panstart', event);
|
|
}
|
|
else if (event.type === 'panmove') {
|
|
// 关键修复:基于当前缩放比例修正移动量
|
|
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;
|
|
|
|
console.log(`平移: deltaX=${event.deltaX}, deltaY=${event.deltaY} | 修正后: dx=${dx}, dy=${dy}`);
|
|
|
|
this.transformMatrix.translate(dx, dy);
|
|
}
|
|
});
|
|
|
|
// 缩放手势 - 修复版本
|
|
this.at.on('pinch', (event) => {
|
|
if (event.type === 'pinchstart') {
|
|
this.lastScale = 1;
|
|
}
|
|
else if (event.type === 'pinchmove') {
|
|
// 计算缩放变化量
|
|
const scaleChange = event.scale / this.lastScale;
|
|
this.lastScale = event.scale;
|
|
|
|
// 使用两指中心点
|
|
const centerX = event.center.x;
|
|
const centerY = event.center.y;
|
|
|
|
console.log(`缩放: scale=${event.scale} | 变化=${scaleChange} | 中心点: (${centerX}, ${centerY})`);
|
|
|
|
// 应用缩放
|
|
this.transformMatrix.scale(scaleChange, scaleChange, centerX, centerY);
|
|
}
|
|
});
|
|
|
|
// 点击手势
|
|
this.at.on('tap', (event) => {
|
|
console.log('点击事件', event);
|
|
});
|
|
|
|
// 长按手势
|
|
this.at.on('press', (event) => {
|
|
console.log('长按事件', event);
|
|
});
|
|
}
|
|
|
|
|
|
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]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 基础平移手势处理
|
|
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};
|
|
}
|
|
|
|
// 基础缩放手势处理
|
|
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}
|
|
];
|
|
}
|
|
}
|
|
|
|
export default GestureHandler; |