touch2mouse
Version:
可以将指定的dom元素触摸操作转换为鼠标操作信号
1,058 lines (918 loc) • 34.6 kB
JavaScript
/**
* 触摸事件处理类
* 封装触摸事件到鼠标事件的转换逻辑
*/
export default class TouchEventHandler {
constructor(options = {}) {
// 配置选项
this.options = {
// 最小移动阈值,避免微小抖动
minMovementThreshold: options.minMovementThreshold || 3,
// 最小缩放阈值,避免微小变化
minScaleThreshold: options.minScaleThreshold || 5,
// 缩放强度基础值
scaleBaseDelta: options.scaleBaseDelta || 500,
// 缩放强度倍数
scaleIntensityMultiplier: options.scaleIntensityMultiplier || 1,
...options
};
// 状态数据
this.touchPoints = []; // 当前触摸点
this.boundaryCenter = null; // 边界中心点
this.previousTouchPoints = []; // 上一帧的触摸点
this.previousBoundaryCenter = null; // 上一帧的边界中心点
this.gestureInfo = null; // 当前手势信息
this.isGestureActive = false; // 是否正在进行手势
this.scaleInfo = null; // 缩放信息
// 目标元素
this.targetElement = null;
// 长按手势识别 - 按下保持不动一段时间触发
this.holdThreshold = options.holdThreshold || 800; // 长按时间阈值(ms)
this.holdPositionThreshold = options.holdPositionThreshold || 30; // 长按位置阈值(px)
// 单指长按状态
this.singleHoldState = {
startTime: 0,
startPosition: null,
timer: null,
isHolding: false
};
// 双指长按状态
this.doubleHoldState = {
startTime: 0,
startPositions: [],
timer: null,
isHolding: false
};
// 三指长按状态
this.tripleHoldState = {
startTime: 0,
startPositions: [],
timer: null,
isHolding: false
};
this.isMouseDownTriggered = false; // 是否已触发鼠标按下
this.currentMouseButton = 0; // 当前按下的鼠标按键 (0: 左键, 1: 中键, 2: 右键)
}
/**
* 设置目标元素
* @param {HTMLElement} element - 目标DOM元素
*/
setTargetElement(element) {
this.targetElement = element;
}
/**
* 触摸开始事件处理
* @param {TouchEvent} e - 触摸事件对象
*/
handleTouchStart(e) {
e.preventDefault(); // 防止页面滚动
this.updateTouchPoints(e.touches);
this.isGestureActive = true;
this.gestureInfo = null;
// 根据手指数量进行不同的长按检测
if (this.touchPoints.length === 1) {
this.startSingleHold(this.touchPoints[0]);
} else if (this.touchPoints.length === 2) {
this.startDoubleHold(this.touchPoints);
} else if (this.touchPoints.length === 3) {
this.startTripleHold(this.touchPoints);
}
console.log('触摸开始:', this.touchPoints.length, '个触摸点');
}
/**
* 触摸移动事件处理
* @param {TouchEvent} e - 触摸事件对象
*/
handleTouchMove(e) {
e.preventDefault(); // 防止页面滚动
this.updateTouchPoints(e.touches);
// 检查长按状态 - 如果移动超出阈值,取消长按
this.checkHoldMovement();
// 进行手势识别
if (this.isGestureActive && this.previousTouchPoints.length > 0) {
this.recognizeGesture();
}
}
/**
* 触摸结束事件处理
* @param {TouchEvent} e - 触摸事件对象
*/
handleTouchEnd(e) {
e.preventDefault();
this.updateTouchPoints(e.touches);
console.log('触摸结束:', this.touchPoints.length, '个触摸点');
// 如果没有触摸点了,清除中心点和手势信息
if (this.touchPoints.length === 0) {
// 清除所有长按状态
this.clearAllHoldStates();
// 如果鼠标已被按下,根据按键类型触发相应的弹起事件
if (this.isMouseDownTriggered) {
if (this.currentMouseButton === 0) {
this.triggerMouseUp(); // 左键弹起
console.log('所有手指离开屏幕 - 触发左键弹起');
} else if (this.currentMouseButton === 2) {
this.triggerRightMouseUp(); // 右键弹起
console.log('所有手指离开屏幕 - 触发右键弹起');
} else if (this.currentMouseButton === 1) {
this.triggerMiddleMouseUp(); // 中键弹起
console.log('所有手指离开屏幕 - 触发中键弹起');
}
this.isMouseDownTriggered = false;
this.currentMouseButton = 0;
}
this.boundaryCenter = null;
this.isGestureActive = false;
this.gestureInfo = null;
this.scaleInfo = null;
this.previousTouchPoints = [];
this.previousBoundaryCenter = null;
}
}
/**
* 触摸取消事件处理
* @param {TouchEvent} e - 触摸事件对象
*/
handleTouchCancel(e) {
e.preventDefault();
// 清除所有长按状态
this.clearAllHoldStates();
// 如果鼠标已被按下,根据按键类型触发相应的弹起事件
if (this.isMouseDownTriggered) {
if (this.currentMouseButton === 0) {
this.triggerMouseUp(); // 左键弹起
console.log('触摸取消 - 触发左键弹起');
} else if (this.currentMouseButton === 2) {
this.triggerRightMouseUp(); // 右键弹起
console.log('触摸取消 - 触发右键弹起');
} else if (this.currentMouseButton === 1) {
this.triggerMiddleMouseUp(); // 中键弹起
console.log('触摸取消 - 触发中键弹起');
}
this.isMouseDownTriggered = false;
this.currentMouseButton = 0;
}
this.touchPoints = [];
this.boundaryCenter = null;
this.isGestureActive = false;
this.gestureInfo = null;
this.scaleInfo = null;
this.previousTouchPoints = [];
this.previousBoundaryCenter = null;
console.log('触摸取消');
}
/**
* 鼠标移动事件处理
* @param {MouseEvent} e - 鼠标事件对象
*/
handleMouseMove(e) {
if (!this.targetElement) return;
const rect = this.targetElement.getBoundingClientRect();
const x = e.offsetX !== undefined ? e.offsetX : e.clientX - rect.left;
const y = e.offsetY !== undefined ? e.offsetY : e.clientY - rect.top;
// 如果没有触摸点,将鼠标位置作为boundaryCenter显示
if (this.touchPoints.length === 0) {
this.boundaryCenter = {
x: x,
y: y
};
}
return e; // 返回事件对象供外部使用
}
/**
* 更新触摸点坐标
* @param {TouchList} touches - 触摸点列表
*/
updateTouchPoints(touches) {
if (!this.targetElement) return;
const rect = this.targetElement.getBoundingClientRect();
// 保存上一帧的数据
this.previousTouchPoints = [...this.touchPoints];
this.previousBoundaryCenter = this.boundaryCenter ? { ...this.boundaryCenter } : null;
this.touchPoints = Array.from(touches).map((touch, index) => ({
id: touch.identifier,
x: touch.clientX - rect.left,
y: touch.clientY - rect.top,
index: index
}));
// 计算边界中心点
this.calculateBoundaryCenter();
}
/**
* 计算边界中心点(边界法算法)
*/
calculateBoundaryCenter() {
if (this.touchPoints.length === 0) {
this.boundaryCenter = null;
return;
}
// 单点触摸
if (this.touchPoints.length === 1) {
this.boundaryCenter = {
...this.touchPoints[0],
width: 0,
height: 0,
area: 0,
touchCount: 1,
isMouseMode: false
};
// 触发mousemove事件(不管鼠标是否按下)
this.triggerMouseMove();
return;
}
// 多点触摸:计算边界中心
let minX = this.touchPoints[0].x, maxX = this.touchPoints[0].x;
let minY = this.touchPoints[0].y, maxY = this.touchPoints[0].y;
for (let point of this.touchPoints) {
minX = Math.min(minX, point.x);
maxX = Math.max(maxX, point.x);
minY = Math.min(minY, point.y);
maxY = Math.max(maxY, point.y);
}
const width = maxX - minX;
const height = maxY - minY;
const area = width * height;
this.boundaryCenter = {
x: (minX + maxX) / 2,
y: (minY + maxY) / 2,
width: width,
height: height,
area: area,
touchCount: this.touchPoints.length,
isMouseMode: false
};
// 触发mousemove事件(不管鼠标是否按下)
this.triggerMouseMove();
}
/**
* 手势识别核心方法
*/
recognizeGesture() {
const currentPoints = this.touchPoints;
const previousPoints = this.previousTouchPoints;
// 确保触摸点数量一致
if (currentPoints.length !== previousPoints.length || currentPoints.length === 0) {
return;
}
// 识别中心点位移(所有触摸点数量都适用)
this.recognizeCenterMovement();
// 双点及以上触摸 - 只识别缩放手势
if (currentPoints.length >= 2) {
this.recognizeScaleGesture(currentPoints, previousPoints);
}
}
/**
* 识别中心点位移
*/
recognizeCenterMovement() {
if (!this.boundaryCenter || !this.previousBoundaryCenter) {
return;
}
const deltaX = this.boundaryCenter.x - this.previousBoundaryCenter.x;
const deltaY = this.boundaryCenter.y - this.previousBoundaryCenter.y;
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// 设置最小移动阈值,避免微小抖动
if (distance < this.options.minMovementThreshold) {
return;
}
// 判断主要移动方向
let direction = '';
if (Math.abs(deltaX) > Math.abs(deltaY)) {
direction = deltaX > 0 ? '右' : '左';
} else {
direction = deltaY > 0 ? '下' : '上';
}
this.gestureInfo = {
type: 'center_movement',
deltaX: deltaX,
deltaY: deltaY,
distance: distance,
direction: direction,
center: { ...this.boundaryCenter },
touchCount: this.touchPoints.length
};
}
/**
* 获取当前状态数据
* @returns {Object} 状态数据对象
*/
getState() {
return {
touchPoints: this.touchPoints,
boundaryCenter: this.boundaryCenter,
gestureInfo: this.gestureInfo,
scaleInfo: this.scaleInfo,
isGestureActive: this.isGestureActive
};
}
/**
* 识别缩放手势(适用于2个及以上触摸点)
*/
recognizeScaleGesture(currentPoints, previousPoints) {
if (currentPoints.length < 2) {
return;
}
// 计算当前所有点的平均距离(相对于中心点)
const currentCenter = this.boundaryCenter;
const previousCenter = this.previousBoundaryCenter;
if (!currentCenter || !previousCenter) {
return;
}
// 计算当前帧所有点到中心的平均距离
let currentAvgDistance = 0;
for (let point of currentPoints) {
const dx = point.x - currentCenter.x;
const dy = point.y - currentCenter.y;
currentAvgDistance += Math.sqrt(dx * dx + dy * dy);
}
currentAvgDistance /= currentPoints.length;
// 计算上一帧所有点到中心的平均距离
let previousAvgDistance = 0;
for (let point of previousPoints) {
const dx = point.x - previousCenter.x;
const dy = point.y - previousCenter.y;
previousAvgDistance += Math.sqrt(dx * dx + dy * dy);
}
previousAvgDistance /= previousPoints.length;
// 避免除零错误
if (previousAvgDistance < 1) {
return;
}
const scale = currentAvgDistance / previousAvgDistance;
const distanceChange = currentAvgDistance - previousAvgDistance;
// 设置缩放阈值,避免微小变化
if (Math.abs(distanceChange) < this.options.minScaleThreshold) {
return;
}
this.scaleInfo = {
scale: scale,
distanceChange: distanceChange,
currentAvgDistance: currentAvgDistance,
previousAvgDistance: previousAvgDistance,
isZoomIn: scale > 1,
isZoomOut: scale < 1,
center: { ...currentCenter },
touchCount: currentPoints.length
};
// 通过模拟handleWheel来控制缩放显示
this.simulateWheelFromTouch(this.scaleInfo);
console.log('缩放手势:', this.scaleInfo);
}
/**
* 模拟handleWheel的数据(由触摸缩放触发)
*/
simulateWheelFromTouch(scaleInfo) {
if (!scaleInfo || !this.boundaryCenter || !this.targetElement) {
return;
}
// 计算模拟的deltaY值(增强强度)
const isZoomIn = scaleInfo.isZoomIn;
const scaleChange = Math.abs(scaleInfo.scale - 1);
const wheelDelta = isZoomIn ?
this.options.scaleBaseDelta * scaleChange * this.options.scaleIntensityMultiplier :
-this.options.scaleBaseDelta * scaleChange * this.options.scaleIntensityMultiplier;
// 创建真实的WheelEvent
const wheelEvent = new WheelEvent('wheel', {
clientX: this.boundaryCenter.x,
clientY: this.boundaryCenter.y,
screenX: this.boundaryCenter.x,
screenY: this.boundaryCenter.y,
deltaX: 0,
deltaY: wheelDelta,
deltaZ: 0,
deltaMode: 0, // DOM_DELTA_PIXEL
button: 0,
buttons: 0,
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(wheelEvent, 'offsetX', {
value: this.boundaryCenter.x,
writable: false
});
Object.defineProperty(wheelEvent, 'offsetY', {
value: this.boundaryCenter.y,
writable: false
});
Object.defineProperty(wheelEvent, 'wheelDelta', {
value: wheelDelta,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(wheelEvent);
console.log('触发滚轮事件:', {
wheelDelta: wheelDelta,
deltaY: wheelDelta,
direction: isZoomIn ? '放大' : '缩小',
scale: scaleInfo.scale,
position: { x: this.boundaryCenter.x, y: this.boundaryCenter.y }
});
}
/**
* 开始单指长按检测 - 触发左键
* @param {Object} touchPoint - 触摸点对象
*/
startSingleHold(touchPoint) {
this.clearOtherHoldStates('single');
const currentTime = Date.now();
const currentPosition = { x: touchPoint.x, y: touchPoint.y };
// 清除之前的定时器
if (this.singleHoldState.timer) {
clearTimeout(this.singleHoldState.timer);
this.singleHoldState.timer = null;
}
// 设置长按开始状态
this.singleHoldState.startTime = currentTime;
this.singleHoldState.startPosition = currentPosition;
this.singleHoldState.isHolding = true;
console.log('单指长按开始检测');
// 设置长按定时器
this.singleHoldState.timer = setTimeout(() => {
// 检查是否还在长按状态且鼠标未被按下
if (this.singleHoldState.isHolding && !this.isMouseDownTriggered) {
this.triggerMouseDown();
this.isMouseDownTriggered = true;
this.currentMouseButton = 0; // 左键
console.log('单指长按检测成功 - 触发左键按下');
}
}, this.holdThreshold);
}
/**
* 开始双指长按检测 - 触发右键
* @param {Array} touchPoints - 触摸点数组
*/
startDoubleHold(touchPoints) {
console.log('双指长按检测开始,触摸点数量:', touchPoints.length);
this.clearOtherHoldStates('double');
const currentTime = Date.now();
const currentPositions = touchPoints.map(point => ({ x: point.x, y: point.y }));
console.log('双指当前位置:', currentPositions);
// 清除之前的定时器
if (this.doubleHoldState.timer) {
clearTimeout(this.doubleHoldState.timer);
this.doubleHoldState.timer = null;
}
// 设置长按开始状态
this.doubleHoldState.startTime = currentTime;
this.doubleHoldState.startPositions = currentPositions;
this.doubleHoldState.isHolding = true;
console.log('双指长按开始检测');
// 设置长按定时器
this.doubleHoldState.timer = setTimeout(() => {
// 检查是否还在长按状态且鼠标未被按下
if (this.doubleHoldState.isHolding && !this.isMouseDownTriggered) {
console.log('双指长按检测成功 - 准备触发右键按下, boundaryCenter:', this.boundaryCenter);
this.triggerRightMouseDown();
this.isMouseDownTriggered = true;
this.currentMouseButton = 2; // 右键
console.log('双指长按检测成功 - 触发右键按下');
}
}, this.holdThreshold);
}
/**
* 开始三指长按检测 - 触发中键
* @param {Array} touchPoints - 触摸点数组
*/
startTripleHold(touchPoints) {
this.clearOtherHoldStates('triple');
const currentTime = Date.now();
const currentPositions = touchPoints.map(point => ({ x: point.x, y: point.y }));
// 清除之前的定时器
if (this.tripleHoldState.timer) {
clearTimeout(this.tripleHoldState.timer);
this.tripleHoldState.timer = null;
}
// 设置长按开始状态
this.tripleHoldState.startTime = currentTime;
this.tripleHoldState.startPositions = currentPositions;
this.tripleHoldState.isHolding = true;
console.log('三指长按开始检测');
// 设置长按定时器
this.tripleHoldState.timer = setTimeout(() => {
// 检查是否还在长按状态且鼠标未被按下
if (this.tripleHoldState.isHolding && !this.isMouseDownTriggered) {
this.triggerMiddleMouseDown();
this.isMouseDownTriggered = true;
this.currentMouseButton = 1; // 中键
console.log('三指长按检测成功 - 触发中键按下');
}
}, this.holdThreshold);
}
/**
* 清除其他长按状态 - 确保互斥
* @param {string} activeType - 当前激活的类型 ('single', 'double', 'triple')
*/
clearOtherHoldStates(activeType) {
if (activeType !== 'single') {
if (this.singleHoldState.timer) {
clearTimeout(this.singleHoldState.timer);
this.singleHoldState.timer = null;
}
this.singleHoldState.isHolding = false;
}
if (activeType !== 'double') {
if (this.doubleHoldState.timer) {
clearTimeout(this.doubleHoldState.timer);
this.doubleHoldState.timer = null;
}
this.doubleHoldState.isHolding = false;
}
if (activeType !== 'triple') {
if (this.tripleHoldState.timer) {
clearTimeout(this.tripleHoldState.timer);
this.tripleHoldState.timer = null;
}
this.tripleHoldState.isHolding = false;
}
}
/**
* 清除所有长按状态
*/
clearAllHoldStates() {
if (this.singleHoldState.timer) {
clearTimeout(this.singleHoldState.timer);
this.singleHoldState.timer = null;
}
this.singleHoldState.isHolding = false;
if (this.doubleHoldState.timer) {
clearTimeout(this.doubleHoldState.timer);
this.doubleHoldState.timer = null;
}
this.doubleHoldState.isHolding = false;
if (this.tripleHoldState.timer) {
clearTimeout(this.tripleHoldState.timer);
this.tripleHoldState.timer = null;
}
this.tripleHoldState.isHolding = false;
}
/**
* 检查长按移动 - 如果移动超出阈值,取消长按
*/
checkHoldMovement() {
// 检查单指长按
if (this.singleHoldState.isHolding && this.touchPoints.length === 1) {
const currentPos = this.touchPoints[0];
const startPos = this.singleHoldState.startPosition;
if (startPos && (Math.abs(currentPos.x - startPos.x) > this.holdPositionThreshold ||
Math.abs(currentPos.y - startPos.y) > this.holdPositionThreshold)) {
console.log('单指移动超出阈值,取消长按');
this.clearOtherHoldStates('none');
}
}
// 检查双指长按
if (this.doubleHoldState.isHolding && this.touchPoints.length === 2) {
const currentPositions = this.touchPoints.map(point => ({ x: point.x, y: point.y }));
const startPositions = this.doubleHoldState.startPositions;
if (startPositions.length === 2 && !this.isPositionsWithinHoldThreshold(currentPositions, startPositions)) {
console.log('双指移动超出阈值,取消长按');
this.clearOtherHoldStates('none');
}
}
// 检查三指长按
if (this.tripleHoldState.isHolding && this.touchPoints.length === 3) {
const currentPositions = this.touchPoints.map(point => ({ x: point.x, y: point.y }));
const startPositions = this.tripleHoldState.startPositions;
if (startPositions.length === 3 && !this.isPositionsWithinHoldThreshold(currentPositions, startPositions)) {
console.log('三指移动超出阈值,取消长按');
this.clearOtherHoldStates('none');
}
}
}
/**
* 检查多个位置是否在阈值范围内
* @param {Array} currentPositions - 当前位置数组
* @param {Array} lastPositions - 上次位置数组
* @returns {boolean} - 是否在阈值范围内
*/
isPositionsWithinThreshold(currentPositions, lastPositions) {
if (currentPositions.length !== lastPositions.length) {
return false;
}
for (let i = 0; i < currentPositions.length; i++) {
const current = currentPositions[i];
const last = lastPositions[i];
if (Math.abs(current.x - last.x) > this.tapPositionThreshold ||
Math.abs(current.y - last.y) > this.tapPositionThreshold) {
return false;
}
}
return true;
}
/**
* 检查多个位置是否在长按阈值范围内
* @param {Array} currentPositions - 当前位置数组
* @param {Array} startPositions - 开始位置数组
* @returns {boolean} - 是否在阈值范围内
*/
isPositionsWithinHoldThreshold(currentPositions, startPositions) {
if (currentPositions.length !== startPositions.length) {
return false;
}
for (let i = 0; i < currentPositions.length; i++) {
const current = currentPositions[i];
const start = startPositions[i];
if (Math.abs(current.x - start.x) > this.holdPositionThreshold ||
Math.abs(current.y - start.y) > this.holdPositionThreshold) {
return false;
}
}
return true;
}
/**
* 触发鼠标按下事件
*/
triggerMouseDown() {
if (!this.targetElement || !this.boundaryCenter) {
return;
}
// 创建真实的MouseEvent
const mouseEvent = new MouseEvent('mousedown', {
clientX: this.boundaryCenter.x,
clientY: this.boundaryCenter.y,
screenX: this.boundaryCenter.x,
screenY: this.boundaryCenter.y,
button: 0, // 左键
buttons: 1, // 左键按下状态
detail: 1, // 点击次数
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(mouseEvent, 'offsetX', {
value: this.boundaryCenter.x,
writable: false
});
Object.defineProperty(mouseEvent, 'offsetY', {
value: this.boundaryCenter.y,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(mouseEvent);
}
/**
* 触发鼠标移动事件
*/
triggerMouseMove() {
if (!this.targetElement || !this.boundaryCenter) {
return;
}
// 计算位移信息
let movementX = 0, movementY = 0;
if (this.gestureInfo && this.gestureInfo.type === 'center_movement') {
movementX = this.gestureInfo.deltaX;
movementY = this.gestureInfo.deltaY;
}
// 创建真实的MouseEvent
const mouseEvent = new MouseEvent('mousemove', {
clientX: this.boundaryCenter.x,
clientY: this.boundaryCenter.y,
screenX: this.boundaryCenter.x,
screenY: this.boundaryCenter.y,
movementX: movementX,
movementY: movementY,
buttons: this.isMouseDownTriggered ? 1 : 0, // 根据鼠标状态设置按键状态
button: -1,
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(mouseEvent, 'offsetX', {
value: this.boundaryCenter.x,
writable: false
});
Object.defineProperty(mouseEvent, 'offsetY', {
value: this.boundaryCenter.y,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(mouseEvent);
}
/**
* 触发鼠标弹起事件
*/
triggerMouseUp() {
if (!this.targetElement) {
return;
}
// 使用当前boundaryCenter或最后已知位置
const centerX = this.boundaryCenter?.x || 0;
const centerY = this.boundaryCenter?.y || 0;
// 创建真实的MouseEvent
const mouseEvent = new MouseEvent('mouseup', {
clientX: centerX,
clientY: centerY,
screenX: centerX,
screenY: centerY,
button: 0, // 左键
buttons: 0, // 无按键按下状态
detail: 1, // 点击次数
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(mouseEvent, 'offsetX', {
value: centerX,
writable: false
});
Object.defineProperty(mouseEvent, 'offsetY', {
value: centerY,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(mouseEvent);
}
/**
* 触发右键按下事件
*/
triggerRightMouseDown() {
if (!this.targetElement || !this.boundaryCenter) {
return;
}
// 创建右键按下事件
const mouseEvent = new MouseEvent('mousedown', {
clientX: this.boundaryCenter.x,
clientY: this.boundaryCenter.y,
screenX: this.boundaryCenter.x,
screenY: this.boundaryCenter.y,
button: 2, // 右键
buttons: 2, // 右键按下状态
detail: 1,
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(mouseEvent, 'offsetX', {
value: this.boundaryCenter.x,
writable: false
});
Object.defineProperty(mouseEvent, 'offsetY', {
value: this.boundaryCenter.y,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(mouseEvent);
}
/**
* 触发右键弹起事件
*/
triggerRightMouseUp() {
if (!this.targetElement) {
return;
}
// 使用当前boundaryCenter或最后已知位置
const centerX = this.boundaryCenter?.x || 0;
const centerY = this.boundaryCenter?.y || 0;
// 创建右键弹起事件
const mouseEvent = new MouseEvent('mouseup', {
clientX: centerX,
clientY: centerY,
screenX: centerX,
screenY: centerY,
button: 2, // 右键
buttons: 0, // 无按键按下状态
detail: 1,
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(mouseEvent, 'offsetX', {
value: centerX,
writable: false
});
Object.defineProperty(mouseEvent, 'offsetY', {
value: centerY,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(mouseEvent);
}
/**
* 触发中键按下事件
*/
triggerMiddleMouseDown() {
if (!this.targetElement || !this.boundaryCenter) {
return;
}
// 创建中键按下事件
const mouseEvent = new MouseEvent('mousedown', {
clientX: this.boundaryCenter.x,
clientY: this.boundaryCenter.y,
screenX: this.boundaryCenter.x,
screenY: this.boundaryCenter.y,
button: 1, // 中键
buttons: 4, // 中键按下状态
detail: 1,
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(mouseEvent, 'offsetX', {
value: this.boundaryCenter.x,
writable: false
});
Object.defineProperty(mouseEvent, 'offsetY', {
value: this.boundaryCenter.y,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(mouseEvent);
}
/**
* 触发中键弹起事件
*/
triggerMiddleMouseUp() {
if (!this.targetElement) {
return;
}
// 使用当前boundaryCenter或最后已知位置
const centerX = this.boundaryCenter?.x || 0;
const centerY = this.boundaryCenter?.y || 0;
// 创建中键弹起事件
const mouseEvent = new MouseEvent('mouseup', {
clientX: centerX,
clientY: centerY,
screenX: centerX,
screenY: centerY,
button: 1, // 中键
buttons: 0, // 无按键按下状态
detail: 1,
altKey: false,
ctrlKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
});
// 添加自定义属性
Object.defineProperty(mouseEvent, 'offsetX', {
value: centerX,
writable: false
});
Object.defineProperty(mouseEvent, 'offsetY', {
value: centerY,
writable: false
});
// 触发真实的DOM事件
this.targetElement.dispatchEvent(mouseEvent);
}
/**
* 销毁实例,清理资源
*/
destroy() {
// 清理所有长按检测定时器
if (this.singleHoldState.timer) {
clearTimeout(this.singleHoldState.timer);
this.singleHoldState.timer = null;
}
if (this.doubleHoldState.timer) {
clearTimeout(this.doubleHoldState.timer);
this.doubleHoldState.timer = null;
}
if (this.tripleHoldState.timer) {
clearTimeout(this.tripleHoldState.timer);
this.tripleHoldState.timer = null;
}
this.touchPoints = [];
this.boundaryCenter = null;
this.previousTouchPoints = [];
this.previousBoundaryCenter = null;
this.gestureInfo = null;
this.scaleInfo = null;
this.isGestureActive = false;
this.targetElement = null;
this.isMouseDownTriggered = false;
this.currentMouseButton = 0;
// 重置所有长按状态
this.singleHoldState = { startTime: 0, startPosition: null, timer: null, isHolding: false };
this.doubleHoldState = { startTime: 0, startPositions: [], timer: null, isHolding: false };
this.tripleHoldState = { startTime: 0, startPositions: [], timer: null, isHolding: false };
}
}