同时支持触摸和鼠标事件翻页

This commit is contained in:
xianyi
2025-11-24 09:31:04 +08:00
parent 1bfa9fefe0
commit 88973906a4
2 changed files with 83 additions and 7 deletions

View File

@@ -68,6 +68,19 @@ function createWindow() {
},
});
// 启用触摸事件支持Windows 触摸屏)
mainWindow.webContents.on("did-finish-load", () => {
// 注入触摸事件支持脚本
mainWindow.webContents.executeJavaScript(`
// 确保触摸事件可用
if (navigator.maxTouchPoints === 0) {
console.log('[Electron] 未检测到触摸设备,将使用鼠标事件模拟');
} else {
console.log('[Electron] 检测到触摸设备,触摸点数:', navigator.maxTouchPoints);
}
`).catch(err => log.error("Failed to inject touch support:", err));
});
const isDev = !app.isPackaged;
if (isDev) {

View File

@@ -1,4 +1,4 @@
import React, { useState, useRef, useEffect } from "react";
import React, { useState, useRef, useEffect, useCallback } from "react";
import { Document, Page, pdfjs } from "react-pdf";
import "react-pdf/dist/esm/Page/AnnotationLayer.css";
import "./UI8.css";
@@ -143,7 +143,7 @@ const UI8: React.FC = () => {
setLoading(false);
};
const goToPrevPage = () => {
const goToPrevPage = useCallback(() => {
if (isAnimating || pageNumber <= 1) return;
setIsAnimating(true);
setAnimationDirection("down");
@@ -152,9 +152,9 @@ const UI8: React.FC = () => {
setIsAnimating(false);
setAnimationDirection(null);
}, 300);
};
}, [isAnimating, pageNumber]);
const goToNextPage = () => {
const goToNextPage = useCallback(() => {
if (isAnimating || pageNumber >= numPages) return;
setIsAnimating(true);
setAnimationDirection("up");
@@ -163,19 +163,24 @@ const UI8: React.FC = () => {
setIsAnimating(false);
setAnimationDirection(null);
}, 300);
};
}, [isAnimating, pageNumber, numPages]);
// 监听触摸事件实现上下滑动翻页
// 监听触摸和鼠标事件实现上下滑动翻页
useEffect(() => {
const container = scrollContainerRef.current;
if (!container) return;
let isDragging = false;
let startY = 0;
// 触摸事件处理
const handleTouchStart = (e: TouchEvent) => {
const touch = e.touches[0];
touchStartRef.current = {
x: touch.clientX,
y: touch.clientY,
};
window.electronAPI?.log("info", `触摸开始: (${touch.clientX}, ${touch.clientY})`);
};
const handleTouchEnd = (e: TouchEvent) => {
@@ -185,14 +190,18 @@ const UI8: React.FC = () => {
const deltaX = touch.clientX - touchStartRef.current.x;
const deltaY = touch.clientY - touchStartRef.current.y;
window.electronAPI?.log("info", `触摸结束: delta(${deltaX}, ${deltaY})`);
// 判断是否为有效滑动至少50px且垂直滑动大于水平滑动
const minSwipeDistance = 50;
if (Math.abs(deltaY) > minSwipeDistance && Math.abs(deltaY) > Math.abs(deltaX)) {
if (deltaY < 0) {
// 向上滑动 = 下一页
window.electronAPI?.log("info", "向上滑动 -> 下一页");
goToNextPage();
} else if (deltaY > 0) {
// 向下滑动 = 上一页
window.electronAPI?.log("info", "向下滑动 -> 上一页");
goToPrevPage();
}
}
@@ -204,16 +213,70 @@ const UI8: React.FC = () => {
touchStartRef.current = null;
};
// 鼠标事件处理(作为触摸的后备方案)
const handleMouseDown = (e: MouseEvent) => {
isDragging = true;
startY = e.clientY;
window.electronAPI?.log("info", `鼠标按下: (${e.clientX}, ${e.clientY})`);
};
const handleMouseMove = (e: MouseEvent) => {
if (!isDragging) return;
// 防止页面滚动
e.preventDefault();
};
const handleMouseUp = (e: MouseEvent) => {
if (!isDragging) return;
const deltaY = e.clientY - startY;
window.electronAPI?.log("info", `鼠标释放: deltaY=${deltaY}`);
// 判断是否为有效滑动至少50px
const minSwipeDistance = 50;
if (Math.abs(deltaY) > minSwipeDistance) {
if (deltaY < 0) {
// 向上拖动 = 下一页
window.electronAPI?.log("info", "向上拖动 -> 下一页");
goToNextPage();
} else if (deltaY > 0) {
// 向下拖动 = 上一页
window.electronAPI?.log("info", "向下拖动 -> 上一页");
goToPrevPage();
}
}
isDragging = false;
};
// 注册触摸事件
container.addEventListener("touchstart", handleTouchStart, { passive: true });
container.addEventListener("touchend", handleTouchEnd, { passive: true });
container.addEventListener("touchcancel", handleTouchCancel, { passive: true });
// 鼠标离开处理
const handleMouseLeave = () => {
isDragging = false;
};
// 注册鼠标事件(作为后备)
container.addEventListener("mousedown", handleMouseDown);
container.addEventListener("mousemove", handleMouseMove);
container.addEventListener("mouseup", handleMouseUp);
container.addEventListener("mouseleave", handleMouseLeave);
return () => {
// 清理触摸事件
container.removeEventListener("touchstart", handleTouchStart);
container.removeEventListener("touchend", handleTouchEnd);
container.removeEventListener("touchcancel", handleTouchCancel);
// 清理鼠标事件
container.removeEventListener("mousedown", handleMouseDown);
container.removeEventListener("mousemove", handleMouseMove);
container.removeEventListener("mouseup", handleMouseUp);
container.removeEventListener("mouseleave", handleMouseLeave);
};
}, [numPages, pageNumber]);
}, [goToNextPage, goToPrevPage]);
return (
<div className="basic-root">