选择导航方式
@@ -393,11 +395,11 @@ const formalPageHeightStyle = computed(() => sectionHeightStyle(data.value.forma
const pageHeightStyle = (page) => sectionHeightStyle(page.height)
const closeDrawer = () => { isDrawerOpen.value = false }
-const pageScrollTop = () => window.scrollY || document.documentElement.scrollTop || document.body.scrollTop || 0
-const pageScrollMax = () => Math.max(0, document.documentElement.scrollHeight - window.innerHeight)
const handleScroll = () => {
- const max = pageScrollMax()
- progress.value = max > 0 ? pageScrollTop() / max : 0
+ const el = scrollContainerRef.value
+ if (!el) return
+ const max = el.scrollHeight - el.clientHeight
+ progress.value = max > 0 ? el.scrollTop / max : 0
if (isAtBottom()) scheduleBottomReturn()
else clearBottomReturn()
}
@@ -413,7 +415,10 @@ const handleUserInteraction = () => {
const sectionEls = () => Array.from(scrollContainerRef.value?.querySelectorAll('.page-section') || [])
-const isAtBottom = () => pageScrollMax() - pageScrollTop() <= 8
+const isAtBottom = () => {
+ const el = scrollContainerRef.value
+ return !!el && el.scrollHeight - el.clientHeight - el.scrollTop <= 8
+}
const clearBottomReturn = () => {
clearTimeout(bottomReturnTimer)
@@ -421,7 +426,8 @@ const clearBottomReturn = () => {
}
const scheduleBottomReturn = (reset = false) => {
- if (!isAtBottom() || !isAutoScroll.value) return
+ const el = scrollContainerRef.value
+ if (!el || !isAtBottom() || !isAutoScroll.value) return
if (bottomReturnTimer && !reset) return
clearBottomReturn()
bottomReturnTimer = setTimeout(() => {
@@ -437,22 +443,26 @@ const scheduleBottomReturn = (reset = false) => {
// 带时长的平滑滚动(easeInOutQuad),duration 由后台 pageSwitchDuration 控制
const smoothScrollTo = (target, duration) => {
+ const el = scrollContainerRef.value
+ if (!el) return
cancelAnimationFrame(animId)
- const start = pageScrollTop(), dist = target - start
+ const start = el.scrollTop, dist = target - start
if (!dist) return
- if (duration <= 0) { window.scrollTo(0, target); return }
+ if (duration <= 0) { el.scrollTop = target; return }
const t0 = performance.now()
const tick = (now) => {
const p = Math.min(1, (now - t0) / duration)
const e = p < 0.5 ? 2 * p * p : 1 - Math.pow(-2 * p + 2, 2) / 2
- window.scrollTo(0, start + dist * e)
+ el.scrollTop = start + dist * e
if (p < 1) animId = requestAnimationFrame(tick)
}
animId = requestAnimationFrame(tick)
}
const goNextSection = () => {
- const top = pageScrollTop()
+ const el = scrollContainerRef.value
+ if (!el) return
+ const top = el.scrollTop
const next = sectionEls().find((e) => e.offsetTop > top + 12)
if (next) {
smoothScrollTo(next.offsetTop, switchDuration.value)
@@ -481,7 +491,7 @@ const startAutoScroll = () => {
if (isAtBottom()) {
scheduleBottomReturn()
} else {
- window.scrollTo(0, pageScrollTop() + FREE_SCROLL_BASE_STEP * (dt / freeInterval.value))
+ scrollContainerRef.value.scrollTop += FREE_SCROLL_BASE_STEP * (dt / freeInterval.value)
if (isAtBottom()) scheduleBottomReturn()
}
}
@@ -491,10 +501,6 @@ const startAutoScroll = () => {
}
}
-const syncPageScrollMode = () => {
- document.documentElement.classList.toggle('page-scroll-snap', data.value.scrollMode === 'snap')
-}
-
const scheduleAutoScrollStart = () => {
clearTimeout(scrollStartTimer)
scrollStartTimer = setTimeout(() => startAutoScroll(), firstScreenDuration.value)
@@ -574,9 +580,6 @@ const handleSubmitRsvp = async () => {
}
onMounted(async () => {
- if ('scrollRestoration' in history) history.scrollRestoration = 'manual'
- window.scrollTo(0, 0)
-
try {
const res = await getConfig()
if (res.data && res.data !== '{}') {
@@ -597,8 +600,6 @@ onMounted(async () => {
}
} catch (e) { /* 使用默认配置 */ }
- syncPageScrollMode()
-
if (data.value.introEnabled) showIntro.value = true
audio.setTracks(data.value.musicList, data.value.activeMusicUrl)
@@ -613,13 +614,10 @@ onMounted(async () => {
scheduleAutoScrollStart()
}
- window.addEventListener('scroll', handleScroll, { passive: true })
handleScroll()
})
onUnmounted(() => {
- document.documentElement.classList.remove('page-scroll-snap')
- window.removeEventListener('scroll', handleScroll)
cancelAnimationFrame(rafId)
cancelAnimationFrame(animId)
clearInterval(snapTimer)
@@ -630,7 +628,6 @@ onUnmounted(() => {
clearBottomReturn()
})
-watch(() => data.value.scrollMode, syncPageScrollMode)
watch(freeScrollSignature, restartAutoScroll)
@@ -640,12 +637,6 @@ watch(freeScrollSignature, restartAutoScroll)
font-variant-numeric: lining-nums;
text-rendering: geometricPrecision;
}
-:global(html.page-scroll-snap) {
- scroll-snap-type: y mandatory;
-}
-:global(html.page-scroll-snap body) {
- scroll-snap-type: y mandatory;
-}
.wrapper .font-serif { font-family: var(--font-serif); }
.wrapper .font-sans { font-family: var(--font-sans); }
.control-btn {
@@ -658,7 +649,7 @@ watch(freeScrollSignature, restartAutoScroll)
}
.formal-main {
font-family: var(--font-calligraphy);
- font-size: 25px;
+ font-size: 24px;
line-height: 1.9;
font-weight: 800;
letter-spacing: 0.32em;