TouchEvent.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { useRef, useCallback } from 'react';
  2. // 设备实际分辨率(竖屏)
  3. const DEVICE_WIDTH = 1280;
  4. const DEVICE_HEIGHT = 2400;
  5. // 触摸事件处理逻辑:坐标转换和手势模拟
  6. export function useTouchEvents(currentDevice, imageRef) {
  7. const isDragging = useRef(false);
  8. const startPos = useRef({ x: 0, y: 0 });
  9. const lastPos = useRef({ x: 0, y: 0 });
  10. const touchStartTime = useRef(0);
  11. // 将鼠标坐标转换为设备坐标
  12. const convertToDeviceCoords = useCallback((clientX, clientY) => {
  13. if (!imageRef.current) {
  14. return null;
  15. }
  16. const img = imageRef.current;
  17. const rect = img.getBoundingClientRect();
  18. // 计算鼠标相对于图片的位置(0-1 范围)
  19. const relativeX = (clientX - rect.left) / rect.width;
  20. const relativeY = (clientY - rect.top) / rect.height;
  21. // 转换为设备坐标
  22. const deviceX = Math.round(relativeX * DEVICE_WIDTH);
  23. const deviceY = Math.round(relativeY * DEVICE_HEIGHT);
  24. // 确保坐标在设备范围内
  25. const clampedX = Math.max(0, Math.min(DEVICE_WIDTH - 1, deviceX));
  26. const clampedY = Math.max(0, Math.min(DEVICE_HEIGHT - 1, deviceY));
  27. return { x: clampedX, y: clampedY };
  28. }, [imageRef]);
  29. // 发送 tap 事件到设备
  30. const sendTap = useCallback(async (x, y) => {
  31. if (!currentDevice || !window.electronAPI || !window.electronAPI.sendTap) {
  32. console.warn('Tap API 不可用或设备未连接');
  33. return;
  34. }
  35. try {
  36. const result = await window.electronAPI.sendTap(currentDevice, x, y);
  37. if (!result?.success) {
  38. console.error('Tap 失败:', result?.error);
  39. }
  40. } catch (err) {
  41. console.error('Tap 异常:', err);
  42. }
  43. }, [currentDevice]);
  44. // 发送 swipe 事件到设备
  45. const sendSwipe = useCallback(async (x1, y1, x2, y2, duration = 300) => {
  46. if (!currentDevice || !window.electronAPI || !window.electronAPI.sendSwipe) {
  47. console.warn('Swipe API 不可用或设备未连接');
  48. return;
  49. }
  50. try {
  51. const result = await window.electronAPI.sendSwipe(currentDevice, x1, y1, x2, y2, duration);
  52. if (!result?.success) {
  53. console.error('Swipe 失败:', result?.error);
  54. }
  55. } catch (err) {
  56. console.error('Swipe 异常:', err);
  57. }
  58. }, [currentDevice]);
  59. // 处理鼠标按下
  60. const handleMouseDown = useCallback((e) => {
  61. if (!currentDevice || !imageRef.current) return;
  62. e.preventDefault();
  63. isDragging.current = true;
  64. touchStartTime.current = Date.now();
  65. const deviceCoords = convertToDeviceCoords(e.clientX, e.clientY);
  66. if (deviceCoords) {
  67. startPos.current = deviceCoords;
  68. lastPos.current = deviceCoords;
  69. }
  70. }, [currentDevice, imageRef, convertToDeviceCoords]);
  71. // 处理鼠标移动
  72. const handleMouseMove = useCallback((e) => {
  73. if (!isDragging.current || !currentDevice || !imageRef.current) return;
  74. e.preventDefault();
  75. const deviceCoords = convertToDeviceCoords(e.clientX, e.clientY);
  76. if (deviceCoords) {
  77. lastPos.current = deviceCoords;
  78. }
  79. }, [currentDevice, imageRef, convertToDeviceCoords]);
  80. // 处理鼠标释放
  81. const handleMouseUp = useCallback((e) => {
  82. if (!isDragging.current || !currentDevice) return;
  83. e.preventDefault();
  84. isDragging.current = false;
  85. const touchDuration = Date.now() - touchStartTime.current;
  86. const distance = Math.sqrt(
  87. Math.pow(lastPos.current.x - startPos.current.x, 2) +
  88. Math.pow(lastPos.current.y - startPos.current.y, 2)
  89. );
  90. // 判断是 tap 还是 swipe
  91. // 如果移动距离小于 10 像素且时间小于 300ms,认为是 tap
  92. if (distance < 10 && touchDuration < 300) {
  93. // Tap 操作
  94. sendTap(startPos.current.x, startPos.current.y);
  95. } else if (distance >= 10) {
  96. // Swipe 操作
  97. const swipeDuration = Math.max(100, Math.min(1000, touchDuration));
  98. sendSwipe(
  99. startPos.current.x,
  100. startPos.current.y,
  101. lastPos.current.x,
  102. lastPos.current.y,
  103. swipeDuration
  104. );
  105. }
  106. }, [currentDevice, sendTap, sendSwipe]);
  107. // 处理鼠标离开(防止拖拽到外部时无法触发 mouseup)
  108. const handleMouseLeave = useCallback((e) => {
  109. if (isDragging.current) {
  110. handleMouseUp(e);
  111. }
  112. }, [handleMouseUp]);
  113. return {
  114. handleMouseDown,
  115. handleMouseMove,
  116. handleMouseUp,
  117. handleMouseLeave,
  118. };
  119. }