导航:修复顶栏隐藏/唤回在滚动徘徊时的抽搐
根因:隐藏/唤回是单事件方向判定——滚动事件里下滑 4px 就藏、往上一有 回弹就现身。拖动页面在阈值附近徘徊时(触控板噪声 / 惯性回弹 / 滚动条 微调都会产生正负几十像素的事件),顶栏每次都被翻转,吸顶头(标题 + 切换 tabs + 发布盒顶部)跟着一起上下滑动——即站主截图里的抽搐。 修复:改成「同向累计迟滞」——滚动事件按方向累计净滚动量(acc), 同向持续累计、反向从新方向重新累计,小幅往复正负抵消: - 累计下滑 40px(且 y > 120,滚出页首区)→ 隐藏 - 隐藏状态下累计上滑 60px → 唤回 - 滚回页首(y ≤ 80)或菜单打开时强制显示(不变) 实测:在阈值附近以 ±70px 快速往复 1.1 秒,翻转 0 次、顶栏稳定; 持续滚动(下滑 → 隐藏、上滑 81px → 唤回、再下滑 → 再隐藏)状态 切换全部正确。prefers-reduced-motion 下过渡照旧禁用。
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user