diff --git a/src/layouts/SiteLayout.vue b/src/layouts/SiteLayout.vue index 48f01f3..4b26f6a 100644 --- a/src/layouts/SiteLayout.vue +++ b/src/layouts/SiteLayout.vue @@ -463,8 +463,7 @@ const CURTAIN_DASH_FALLBACK = 7.2 /** 幕布露出这么多比例即起笔 */ const CURTAIN_DRAW_AT = 0.6 -/** 一划到底:距页面底部不足这么多屏时,下一次向下滑动直接滑到底 */ -const CURTAIN_GLIDE_ZONE = 0.6 +/** 一划到底:只要幕布还露在视口里(即 footer 之后那一段),再一次向下滑动就直接滑到底 */ const CURTAIN_GLIDE_MS = 1100 const curtainSvg = ref(null) @@ -472,6 +471,10 @@ const curtainGroup = ref(null) const curtainSpacer = ref(null) const curtainDrawn = ref(false) +/** 幕布(末尾占位区)是否还在视口里。它就是"footer 之后"那段区域: + * 用户滑到底后往上滑一点、幕布没离开视线,此时再往下滑仍要一划到底 */ +let curtainOnScreen = false + /** v-for 里的 引用,setupCurtain 要逐个量身定位 */ const letterEls: (SVGTextElement | null)[] = [] function setLetterEl(el: Element | ComponentPublicInstance | null, index: number): void { @@ -527,6 +530,8 @@ function watchCurtain(): void { curtainObserver = new IntersectionObserver( (entries) => { entries.forEach((entry) => { + // 幕布在不在视线里,决定"一划到底"生不生效 + curtainOnScreen = entry.isIntersecting if (entry.isIntersecting && entry.intersectionRatio >= CURTAIN_DRAW_AT) { curtainDrawn.value = true } else if (!entry.isIntersecting) { @@ -539,14 +544,17 @@ function watchCurtain(): void { curtainObserver.observe(spacer) } -/** 一划到底:幕布已露头(距底不足 0.6 屏)时再一次向下滑动,就直接滑到底, - * 省得用户在最后半屏里一点点蹭;顺带让描边动画在整块幕布前完整播完 */ +/** 一划到底:幕布还露在视口里时(footer 之后那一段,含滑到底后往上滑一点、幕布没离开视线的情况), + * 再一次向下滑动就直接滑到底,省得用户在最后半屏里一点点蹭; + * 顺带让描边动画在整块幕布前完整播完 */ function glideToBottom(): void { + if (prefersReducedMotion.matches) return // 减弱动态效果下不接管滚动 + if (!curtainOnScreen) return // 幕布已离开视线(还在上面正文里),不插手 const now = performance.now() if (now < curtainGlideUntil) return const doc = document.documentElement const remaining = doc.scrollHeight - window.scrollY - window.innerHeight - if (remaining <= 0 || remaining > window.innerHeight * CURTAIN_GLIDE_ZONE) return + if (remaining <= 0) return // 已经在最底,没什么可滑的 curtainGlideUntil = now + CURTAIN_GLIDE_MS + 300 const top = doc.scrollHeight const lenis = lenisRef?.value