UNPKG

touch2mouse

Version:

可以将指定的dom元素触摸操作转换为鼠标操作信号

1,058 lines (918 loc) 34.6 kB
/** * 触摸事件处理类 * 封装触摸事件到鼠标事件的转换逻辑 */ 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 }; } }