809 字
4 分钟
Fuwari 博客改造计划:为页面添加“双向滚动”控制(置顶与置底)
为什么需要双向滚动?
Fuwari 原生只提供了一个“返回顶部”按钮。但在实际阅读长文或翻阅评论区时,用户往往也需要快速“直达底部”。为了保持界面的一致性,我们将这两个功能整合在同一个视觉区域,通过智能的算法自动判断该显示哪一个按钮,从而提升导航效率。
设计架构
这是一个典型的“状态驱动”交互,我们需要处理好 UI、逻辑与框架生命周期的协作:
1. UI 表现层 (Component Layer)
我们将原有的单按钮组件重构为 flex-col 垂直排列的按钮组。
- 容器定位:使用
fixed定位在屏幕右侧,并利用transform处理初始的隐藏偏移。 - 视觉反馈:通过
transition实现平滑的缩放和位移过渡。
2. 核心逻辑层 (Logic Layer)
- 滚动判定:通过
window.onscroll实时对比scrollTop(当前滚动距离)、clientHeight(视口高度)与scrollHeight(页面总高度)。 - 智能互斥:
- 当页面不在顶部时,显示“返回顶部”。
- 当页面距离底部超过一定阈值(如 100px)时,显示“下滑到底部”。
3. 生命周期适配层 (Integration Layer)
由于 Fuwari 使用了 Swup 路由,页面跳转时 DOM 会被替换。如果只在初次加载时获取按钮引用,跳转后脚本将无法找到新页面的按钮。
- 重新初始化:必须在 Swup 的
page:view钩子中重新执行getElementById,确保逻辑始终绑定在当前的活动元素上。
核心实现步骤
1. 重构基础组件
修改 src/components/control/BackToTop.astro。我们将原来的 ID 移到了内部的按钮容器上,并引入了 Flex 布局。
<div class="scroll-controls-wrapper hidden lg:block"> <div class="scroll-controls-container flex flex-col gap-2"> <!-- 返回顶部 --> <div id="back-to-top-btn" class="scroll-btn hide" onclick="window.scroll({top: 0, behavior: 'smooth'})"> <button class="btn-card h-[3.75rem] w-[3.75rem]"> <Icon name="material-symbols:keyboard-arrow-up-rounded" /> </button> </div> <!-- 下滑到底部 --> <div id="scroll-to-bottom-btn" class="scroll-btn" onclick="window.scroll({top: document.documentElement.scrollHeight, behavior: 'smooth'})"> <button class="btn-card h-[3.75rem] w-[3.75rem]"> <Icon name="material-symbols:keyboard-arrow-down-rounded" /> </button> </div> </div></div>2. 注入全局滚动算法
在 src/layouts/Layout.astro 中找到 scrollFunction 并升级它。
关键代码解析:
function scrollFunction() { let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; let scrollHeight = document.documentElement.scrollHeight; let clientHeight = document.documentElement.clientHeight;
// 如果向下滚动超过 Banner,显示返回顶部 if (scrollTop > bannerHeight) backToTopBtn.classList.remove('hide'); else backToTopBtn.classList.add('hide');
// 如果还没滚到底部(预留100px),显示滑到底部 if (scrollTop + clientHeight < scrollHeight - 100) { scrollToBottomBtn.classList.remove('hide'); } else { scrollToBottomBtn.classList.add('hide'); }}3. 解决 Swup 跳转失效问题
这是很多改造者容易忽略的一步。在 Layout.astro 的 setup 函数中,我们需要监听 page:view 事件来重新获取 DOM 引用:
window.swup.hooks.on('page:view', () => { // 页面跳转后,旧的按钮对象已不存在于文档中,必须重新获取 backToTopBtn = document.getElementById('back-to-top-btn'); scrollToBottomBtn = document.getElementById('scroll-to-bottom-btn');});细节优化建议
- 间距调整:我们在按钮组中使用了
gap-2,确保两个按钮之间有微小的缝隙,防止误触。 - 阴影与背景:复用了 Fuwari 的
btn-card类,使其在暗色模式下也能保持完美的视觉一致性。
结语
通过这次改造,您的博客不仅能“快速回头”,也能“一冲到底”。这种对细节的极致追求,能显著降低用户在长文中的操作疲劳感。
Fuwari 博客改造计划:为页面添加“双向滚动”控制(置顶与置底)
https://fuwari.vercel.app/posts/fuwari博客改造计划为博客添加双向滚动控制/