From 08250b58ef53875a85dc9ac39fae9bbeaad7ff59 Mon Sep 17 00:00:00 2001 From: Sakurasan <26715255+Sakurasan@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:06:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E8=88=AA=EF=BC=9A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=A1=B6=E6=A0=8F=E9=9A=90=E8=97=8F/=E5=94=A4=E5=9B=9E?= =?UTF-8?q?=E5=9C=A8=E6=BB=9A=E5=8A=A8=E5=BE=98=E5=BE=8A=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E6=8A=BD=E6=90=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:隐藏/唤回是单事件方向判定——滚动事件里下滑 4px 就藏、往上一有 回弹就现身。拖动页面在阈值附近徘徊时(触控板噪声 / 惯性回弹 / 滚动条 微调都会产生正负几十像素的事件),顶栏每次都被翻转,吸顶头(标题 + 切换 tabs + 发布盒顶部)跟着一起上下滑动——即站主截图里的抽搐。 修复:改成「同向累计迟滞」——滚动事件按方向累计净滚动量(acc), 同向持续累计、反向从新方向重新累计,小幅往复正负抵消: - 累计下滑 40px(且 y > 120,滚出页首区)→ 隐藏 - 隐藏状态下累计上滑 60px → 唤回 - 滚回页首(y ≤ 80)或菜单打开时强制显示(不变) 实测:在阈值附近以 ±70px 快速往复 1.1 秒,翻转 0 次、顶栏稳定; 持续滚动(下滑 → 隐藏、上滑 81px → 唤回、再下滑 → 再隐藏)状态 切换全部正确。prefers-reduced-motion 下过渡照旧禁用。 --- frontend/src/components/TopBar.vue | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) 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 } }