feat: auto-hide top-bar and cursor after 3s idle, restore on mouse move

This commit is contained in:
2026-06-10 15:35:12 +08:00
parent bf4b09f4e0
commit 642e18fb5e

View File

@@ -43,6 +43,8 @@ const showIntro = ref(false)
const introWatched = ref(false)
const introVideoRef = ref<HTMLVideoElement | null>(null)
const menuVideoRef = ref<HTMLVideoElement | null>(null)
const showTopBar = ref(true)
let hideTopBarTimer: ReturnType<typeof setTimeout> | null = null
const { loadGame, start, resumeAutoSave, makeChoice, clickHotspot, startChapter,
skipScene, setSpeed, getSpeed, isSceneWatched,
@@ -113,6 +115,15 @@ watch([() => store.qteTimeRelax, () => store.qteSingleKey], () => {
applyQteParams()
})
watch(
() => [
showPauseMenu.value, showMenu.value, showChapterSelect.value,
showAchievements.value, showEndingGallery.value, recapChapterId.value,
paused.value, store.showSettings,
],
() => { resetTopBarTimer() },
)
function onVideoReady(elA: HTMLVideoElement, elB: HTMLVideoElement) {
videoElA.value = elA
videoElB.value = elB
@@ -243,6 +254,21 @@ function onQuitToMenu() {
function onGlobalMouseMove() {
store.setInputMode('mouse')
resetTopBarTimer()
}
function anyOverlayOpen(): boolean {
return showPauseMenu.value || showMenu.value || showChapterSelect.value
|| showAchievements.value || showEndingGallery.value || !!recapChapterId.value
|| paused.value || store.showSettings
}
function resetTopBarTimer() {
showTopBar.value = true
if (hideTopBarTimer) clearTimeout(hideTopBarTimer)
if (!anyOverlayOpen()) {
hideTopBarTimer = setTimeout(() => { showTopBar.value = false }, 3000)
}
}
onMounted(() => {
@@ -253,6 +279,7 @@ onMounted(() => {
onUnmounted(() => {
document.removeEventListener('keydown', onGlobalKeydown)
document.removeEventListener('mousemove', onGlobalMouseMove)
if (hideTopBarTimer) clearTimeout(hideTopBarTimer)
})
init()
@@ -271,7 +298,7 @@ init()
<video ref="menuVideoRef" :src="store.menuVideo" class="menu-bg-video" autoplay loop muted></video>
</div>
<div class="game-screen" v-show="started && !store.gameEnded">
<div class="game-screen" :class="{ idle: !showTopBar }" v-show="started && !store.gameEnded">
<GamePlayer v-show="!store.isImageScene" @video-ready="onVideoReady" />
<HotspotLayer
:hotspots="store.hotspots"
@@ -305,7 +332,7 @@ init()
<Transition name="prompt-toast">
<div v-if="showPromptToast" class="prompt-toast">{{ promptToast }}</div>
</Transition>
<div v-if="started && !store.gameEnded" class="top-bar">
<div v-if="started && !store.gameEnded" class="top-bar" :class="{ hidden: !showTopBar }">
<PlaybackBar
:can-skip="canSkip"
:current-speed="currentSpeed"
@@ -438,6 +465,16 @@ html, body {
z-index: 20;
display: flex;
gap: 6px;
transition: opacity 0.3s ease;
}
.top-bar.hidden {
opacity: 0;
pointer-events: none;
}
.game-screen.idle {
cursor: none;
}
.top-btn {