diff --git a/frontend/src/components/TopBar.vue b/frontend/src/components/TopBar.vue index 211350d..8c64378 100644 --- a/frontend/src/components/TopBar.vue +++ b/frontend/src/components/TopBar.vue @@ -27,26 +27,36 @@ function isOn(l) { return l.to === '/' ? route.path === '/' : route.path.startsWith(l.to) } -// 下滑藏顶栏、上滑唤回。dead zone 滤掉手指微抖;滚回页首(没滚出顶栏多远) -// 或菜单开着时强制显示 —— 纸片锚在顶栏下面,顶栏藏了纸片会悬空。 -// 上滑唤回要累计上移 40px 才算数:页面加载后字体/内容稳定时高度会收缩, -// 浏览器把滚动位置回弹几十像素,那种「假上滑」不该把顶栏拉回来。 +// 下滑藏顶栏、上滑唤回。迟滞用「同向累计」:往复拖动时正负抵消, +// 持续同向滚动超过阈值才切换状态——之前的单事件方向判定 +// (下滑 4px 就藏、回弹就现身)在阈值附近徘徊时会抽搐。 +// 滚回页首(y ≤ 80)或菜单开着时强制显示 —— 纸片锚在顶栏下面, +// 顶栏藏了纸片会悬空。 let lastY = typeof window === 'undefined' ? 0 : window.scrollY -let hideY = 0 +let acc = 0 function onScroll() { const y = window.scrollY if (open.value || y <= 80) { hidden.value = false lastY = y + acc = 0 return } const delta = y - lastY lastY = y - if (delta > 4) { + if (delta === 0) return + // 同向累计;反向则从新方向重新累计(小幅往复互相抵消) + if (acc === 0 || (delta > 0) === (acc > 0)) { + acc += delta + } else { + acc = delta + } + if (!hidden.value && acc > 80 && y > 120) { hidden.value = true - hideY = y - } else if (delta < -4 && hideY - y > 40) { + acc = 0 + } else if (hidden.value && acc < -60) { hidden.value = false + acc = 0 } }