import { useRef, useCallback, useState, useEffect } from 'react'; // 触摸事件处理逻辑:坐标转换和手势模拟 export function useTouchEvents(currentDevice, imageRef) { const isDragging = useRef(false); const startPos = useRef({ x: 0, y: 0 }); const lastPos = useRef({ x: 0, y: 0 }); const touchStartTime = useRef(0); const [deviceResolution, setDeviceResolution] = useState({ width: 1280, height: 2400 }); // 获取设备实际分辨率 useEffect(() => { const fetchDeviceResolution = async () => { if (!currentDevice || !window.electronAPI || !window.electronAPI.getDeviceResolution) { // 如果 API 不可用,使用默认值 return; } try { const result = await window.electronAPI.getDeviceResolution(currentDevice); if (result?.success && result.width && result.height) { setDeviceResolution({ width: result.width, height: result.height }); } } catch (err) { // 获取设备分辨率失败,使用默认值 } }; if (currentDevice) { fetchDeviceResolution(); } }, [currentDevice]); // 将鼠标坐标转换为设备坐标 const convertToDeviceCoords = useCallback((clientX, clientY) => { if (!imageRef.current) { return null; } const img = imageRef.current; const rect = img.getBoundingClientRect(); // 获取图片的实际显示尺寸(考虑 object-fit: contain) // 图片可能不会完全填满容器,需要计算实际显示区域 let displayWidth, displayHeight, offsetX, offsetY; if (img.naturalWidth && img.naturalHeight) { // 获取图片的原始尺寸 const imgAspect = img.naturalWidth / img.naturalHeight; const containerAspect = rect.width / rect.height; if (imgAspect > containerAspect) { // 图片更宽,以宽度为准(左右可能有黑边) displayWidth = rect.width; displayHeight = rect.width / imgAspect; offsetX = 0; offsetY = (rect.height - displayHeight) / 2; } else { // 图片更高,以高度为准(上下可能有黑边) displayHeight = rect.height; displayWidth = rect.height * imgAspect; offsetX = (rect.width - displayWidth) / 2; offsetY = 0; } } else { // 如果图片尺寸未知,使用容器尺寸 displayWidth = rect.width; displayHeight = rect.height; offsetX = 0; offsetY = 0; } // 计算鼠标相对于实际显示区域的位置 const relativeX = (clientX - rect.left - offsetX) / displayWidth; const relativeY = (clientY - rect.top - offsetY) / displayHeight; // 检查是否在有效显示区域内(0-1之间) if (relativeX < 0 || relativeX > 1 || relativeY < 0 || relativeY > 1) { // 点击在显示区域外(黑边区域),返回 null return null; } // 转换为设备坐标 const deviceX = Math.round(relativeX * deviceResolution.width); const deviceY = Math.round(relativeY * deviceResolution.height); // 确保坐标在设备范围内 const clampedX = Math.max(0, Math.min(deviceResolution.width - 1, deviceX)); const clampedY = Math.max(0, Math.min(deviceResolution.height - 1, deviceY)); return { x: clampedX, y: clampedY }; }, [imageRef, deviceResolution]); // 发送 tap 事件到设备 const sendTap = useCallback(async (x, y) => { if (!currentDevice || !window.electronAPI || !window.electronAPI.sendTap) { return; } try { const result = await window.electronAPI.sendTap(currentDevice, x, y); if (!result?.success) { // Tap 失败 } } catch (err) { // Tap 异常 } }, [currentDevice]); // 发送 swipe 事件到设备 const sendSwipe = useCallback(async (x1, y1, x2, y2, duration = 300) => { if (!currentDevice || !window.electronAPI || !window.electronAPI.sendSwipe) { return; } try { const result = await window.electronAPI.sendSwipe(currentDevice, x1, y1, x2, y2, duration); if (!result?.success) { // Swipe 失败 } } catch (err) { // Swipe 异常 } }, [currentDevice]); // 处理鼠标按下 const handleMouseDown = useCallback((e) => { if (!currentDevice || !imageRef.current) return; e.preventDefault(); isDragging.current = true; touchStartTime.current = Date.now(); const deviceCoords = convertToDeviceCoords(e.clientX, e.clientY); if (deviceCoords) { startPos.current = deviceCoords; lastPos.current = deviceCoords; } }, [currentDevice, imageRef, convertToDeviceCoords]); // 处理鼠标移动 const handleMouseMove = useCallback((e) => { if (!isDragging.current || !currentDevice || !imageRef.current) return; e.preventDefault(); const deviceCoords = convertToDeviceCoords(e.clientX, e.clientY); if (deviceCoords) { lastPos.current = deviceCoords; } }, [currentDevice, imageRef, convertToDeviceCoords]); // 处理鼠标释放 const handleMouseUp = useCallback((e) => { if (!isDragging.current || !currentDevice) return; e.preventDefault(); isDragging.current = false; const touchDuration = Date.now() - touchStartTime.current; const distance = Math.sqrt( Math.pow(lastPos.current.x - startPos.current.x, 2) + Math.pow(lastPos.current.y - startPos.current.y, 2) ); // 判断是 tap 还是 swipe // 如果移动距离小于 10 像素且时间小于 300ms,认为是 tap if (distance < 10 && touchDuration < 300) { // Tap 操作 sendTap(startPos.current.x, startPos.current.y); } else if (distance >= 10) { // Swipe 操作 const swipeDuration = Math.max(100, Math.min(1000, touchDuration)); sendSwipe( startPos.current.x, startPos.current.y, lastPos.current.x, lastPos.current.y, swipeDuration ); } }, [currentDevice, sendTap, sendSwipe]); // 处理鼠标离开(防止拖拽到外部时无法触发 mouseup) const handleMouseLeave = useCallback((e) => { if (isDragging.current) { handleMouseUp(e); } }, [handleMouseUp]); return { handleMouseDown, handleMouseMove, handleMouseUp, handleMouseLeave, }; }