修复:增加回到顶部功能,优化博客性能

This commit is contained in:
2026-09-21 09:37:31 +08:00
parent b0e7d40faf
commit 219cb712a6
27 changed files with 845 additions and 373 deletions
+59
View File
@@ -0,0 +1,59 @@
import { onPage } from "./lifecycle"
/**
* 回到顶部按钮。
*
* 显隐**默认交给 CSS**:`animation-timeline: scroll(root block)` 让按钮随滚动位置
* 淡入,不需要任何 scroll 监听(见 global.css 的 .back-to-top)。
* 这里只负责两件事:
* 1. 点击后平滑回到顶部;
* 2. 给不支持滚动驱动动画的浏览器(Firefox < 144 / Safari < 26)做降级。
*/
/** 与 global.css 里 animation-range 的起点保持一致 */
const REVEAL_AFTER_PX = 480
const supportsScrollTimeline = () =>
typeof CSS !== "undefined" &&
typeof CSS.supports === "function" &&
CSS.supports("animation-timeline: scroll()")
onPage("back-to-top", () => {
const button = document.querySelector<HTMLElement>("[data-back-to-top]")
if (!button) return
const onClick = () => {
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches
window.scrollTo({ top: 0, behavior: reduceMotion ? "auto" : "smooth" })
}
button.addEventListener("click", onClick)
if (supportsScrollTimeline()) {
return () => button.removeEventListener("click", onClick)
}
// ——— 降级路径 ———
// rAF 节流,且只在跨越阈值时才写 class:滚动本身不产生布局读取(只用 scrollY)
const root = document.documentElement
root.classList.add("no-scroll-timeline")
let frame = 0
const update = () => {
frame = 0
button.classList.toggle("is-visible", window.scrollY > REVEAL_AFTER_PX)
}
const onScroll = () => {
if (frame) return
frame = window.requestAnimationFrame(update)
}
window.addEventListener("scroll", onScroll, { passive: true })
update()
return () => {
window.removeEventListener("scroll", onScroll)
if (frame) window.cancelAnimationFrame(frame)
button.removeEventListener("click", onClick)
root.classList.remove("no-scroll-timeline")
}
})