Skip to content

Commit c5f237c

Browse files
Refactor controls visibility logic on mouse movement
Simplifies and updates the logic for showing and hiding controls based on mouse movement. Controls are now shown immediately on significant mouse movement and hidden after 2 seconds of inactivity, replacing previous text box position checks and visibility logic.
1 parent 7a2cb15 commit c5f237c

1 file changed

Lines changed: 35 additions & 59 deletions

File tree

packages/webgal/src/Stage/Stage.tsx

Lines changed: 35 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { FullScreenPerform } from './FullScreenPerform/FullScreenPerform';
66
import { nextSentence } from '@/Core/controller/gamePlay/nextSentence';
77
import { stopAll } from '@/Core/controller/gamePlay/fastSkip';
88
import { useDispatch, useSelector } from 'react-redux';
9-
import { RootState } from '@/store/store';
9+
import { RootState, webgalStore } from '@/store/store';
1010
import { setVisibility } from '@/store/GUIReducer';
1111
import { TextBoxFilm } from '@/Stage/TextBox/TextBoxFilm';
1212
import { useHotkey } from '@/hooks/useHotkey';
@@ -18,52 +18,12 @@ import { IGuiState } from '@/store/guiInterface';
1818
import { IStageState } from '@/store/stageInterface';
1919
// import OldStage from '@/Components/Stage/OldStage/OldStage';
2020

21-
function inTextBox(event: React.MouseEvent) {
22-
const tb = document.getElementById('textBoxMain');
23-
if (!tb) {
24-
return false;
25-
}
26-
let bounds = tb.getBoundingClientRect();
27-
return (
28-
event.clientX > bounds.left &&
29-
event.clientX < bounds.right &&
30-
event.clientY > bounds.top &&
31-
event.clientY < bounds.bottom
32-
);
33-
}
34-
35-
function checkMousePosition(event: React.MouseEvent, GUIState: IGuiState, dispatch: ReturnType<typeof useDispatch>) {
36-
if (!GUIState.controlsVisibility && inTextBox(event)) {
37-
dispatch(setVisibility({ component: 'controlsVisibility', visibility: true }));
38-
}
39-
if (GUIState.controlsVisibility && !inTextBox(event)) {
40-
dispatch(setVisibility({ component: 'controlsVisibility', visibility: false }));
41-
}
42-
}
43-
44-
function isTextboxHidden(stageState: IStageState, GUIState: IGuiState) {
45-
if (!GUIState.showTextBox) {
46-
return true;
47-
}
48-
49-
if (stageState.isDisableTextbox) {
50-
return true;
51-
}
52-
53-
const isText = stageState.showText !== '' || stageState.showName !== '';
54-
if (!isText) {
55-
return true;
56-
}
57-
58-
const isInIntro = document.getElementById('introContainer')?.style.display === 'block';
59-
if (isInIntro) {
60-
return true;
61-
}
62-
63-
return false;
64-
}
65-
6621
let timeoutEventHandle: ReturnType<typeof setTimeout> | null = null;
22+
// 视为“未移动”的最小移动阈值(像素^2),例如 4px -> 16
23+
const MOVE_THRESHOLD_SQ = 16;
24+
let lastMouseX = 0;
25+
let lastMouseY = 0;
26+
let hasLastMousePos = false;
6727

6828
/**
6929
* 检查并更新控制可见性
@@ -79,22 +39,38 @@ function updateControlsVisibility(
7939
GUIState: IGuiState,
8040
dispatch: ReturnType<typeof useDispatch>,
8141
) {
82-
if (isTextboxHidden(stageState, GUIState)) {
83-
// 当文本框被隐藏时
84-
// 逻辑:鼠标移动时显示,一段时间(默认:1秒)后隐藏
85-
if (timeoutEventHandle) {
86-
clearTimeout(timeoutEventHandle);
87-
}
42+
// 新逻辑:超过阈值的鼠标移动立刻显示,2s 无操作后隐藏(未锁定时)
43+
const { clientX, clientY } = event;
44+
let movedEnough = false;
45+
if (!hasLastMousePos) {
46+
movedEnough = true; // 第一次移动视为足够
47+
hasLastMousePos = true;
48+
} else {
49+
const dx = clientX - lastMouseX;
50+
const dy = clientY - lastMouseY;
51+
movedEnough = dx * dx + dy * dy >= MOVE_THRESHOLD_SQ;
52+
}
53+
lastMouseX = clientX;
54+
lastMouseY = clientY;
55+
56+
if (!movedEnough) {
57+
// 微小移动,视为无操作,不重置计时器
58+
return;
59+
}
60+
61+
if (timeoutEventHandle) {
62+
clearTimeout(timeoutEventHandle);
63+
}
8864

65+
if (!GUIState.controlsVisibility) {
8966
dispatch(setVisibility({ component: 'controlsVisibility', visibility: true }));
90-
timeoutEventHandle = setTimeout(() => {
91-
dispatch(setVisibility({ component: 'controlsVisibility', visibility: false }));
92-
}, 1000);
93-
} else {
94-
// 当文本框正常显示时
95-
// 逻辑:鼠标位置在文本框内时显示
96-
checkMousePosition(event, GUIState, dispatch);
9767
}
68+
69+
timeoutEventHandle = setTimeout(() => {
70+
if (!webgalStore.getState().GUI.showControls) {
71+
dispatch(setVisibility({ component: 'controlsVisibility', visibility: false }));
72+
}
73+
}, 2000);
9874
}
9975

10076
export const Stage: FC = () => {

0 commit comments

Comments
 (0)