更新页面效果
This commit is contained in:
@@ -38,9 +38,9 @@
|
||||
|
||||
<!-- 九宫格 -->
|
||||
<div v-else-if="page.type === 'nine-grid'" class="grid grid-cols-3 gap-1.5 px-4 mt-6">
|
||||
<div v-for="(img, imgIdx) in page.images" :key="imgIdx" v-reveal="{ variant: 'scale', delay: imgIdx * 60 }"
|
||||
class="aspect-square relative" :class="frameClass">
|
||||
<img :src="img" class="hover:scale-105 transition-transform duration-700" />
|
||||
<div v-for="(img, imgIdx) in page.images" :key="imgIdx" v-reveal="{ variant: 'up', delay: imgIdx * 24 }"
|
||||
class="nine-grid-reveal aspect-square relative" :class="frameClass">
|
||||
<img :src="img" loading="lazy" decoding="async" class="nine-grid-img" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -144,6 +144,26 @@ function polaroidTransform(i) {
|
||||
.gallery-subtitle { font-family: var(--font-display); }
|
||||
.gallery-desc { font-family: var(--font-kai); }
|
||||
|
||||
.nine-grid-reveal.reveal {
|
||||
transform: translate3d(0, 12px, 0);
|
||||
transition:
|
||||
opacity 420ms ease-out,
|
||||
transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
.nine-grid-reveal.reveal--in {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.nine-grid-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transform: translateZ(0);
|
||||
transition: transform 420ms ease-out;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
.nine-grid-img:hover { transform: translateZ(0) scale(1.03); }
|
||||
|
||||
/* 错落双图:高度随视口缩放并封顶,保证标题+图片总高始终落在页高预算内 */
|
||||
.overlap-wrap { height: clamp(320px, 54vh, 460px); }
|
||||
|
||||
|
||||
@@ -324,6 +324,7 @@ const rsvpForm = reactive({ name: '', guest_count: '1', wishes: '' })
|
||||
const rsvpOptions = [ { value: '1', label: '1 人出席' }, { value: '2', label: '2 人出席' }, { value: '3', label: '3 人及以上' }, { value: '0', label: '遗憾缺席' } ]
|
||||
|
||||
let rafId = null, snapTimer = null, pauseTimer = null, introTimer = null, freeTimer = null, animId = null, scrollStartTimer = null, bottomReturnTimer = null
|
||||
let freeScrollLastTs = 0
|
||||
const BOTTOM_RETURN_DELAY = 30000
|
||||
|
||||
// 后台可配置的滚动参数(带默认值兜底,防止脏数据)
|
||||
@@ -464,24 +465,30 @@ const startAutoScroll = () => {
|
||||
clearTimeout(scrollStartTimer)
|
||||
clearInterval(snapTimer)
|
||||
clearInterval(freeTimer)
|
||||
cancelAnimationFrame(rafId)
|
||||
if (data.value.scrollMode === 'snap') {
|
||||
if (isAutoScroll.value && !isInteracting.value && !isDrawerOpen.value) goNextSection()
|
||||
snapTimer = setInterval(() => {
|
||||
if (isAutoScroll.value && !isInteracting.value && !isDrawerOpen.value) goNextSection()
|
||||
}, 4500)
|
||||
} else {
|
||||
// 自由滚动:setInterval 按后台配置的间隔匀速推进(间隔越小越快)
|
||||
freeTimer = setInterval(() => {
|
||||
// 自由滚动:按浏览器帧率匀速推进,速度仍由后台间隔控制(间隔越小越快)
|
||||
freeScrollLastTs = 0
|
||||
const tickFreeScroll = (now) => {
|
||||
const dt = freeScrollLastTs ? Math.min(34, now - freeScrollLastTs) : 16.7
|
||||
freeScrollLastTs = now
|
||||
const el = scrollContainerRef.value
|
||||
if (el && isAutoScroll.value && !isInteracting.value && !isDrawerOpen.value) {
|
||||
if (isAtBottom(el)) {
|
||||
scheduleBottomReturn()
|
||||
return
|
||||
} else {
|
||||
el.scrollTop += dt * (1.2 / freeInterval.value)
|
||||
if (isAtBottom(el)) scheduleBottomReturn()
|
||||
}
|
||||
el.scrollTop += 1.2
|
||||
if (isAtBottom(el)) scheduleBottomReturn()
|
||||
}
|
||||
}, freeInterval.value)
|
||||
rafId = requestAnimationFrame(tickFreeScroll)
|
||||
}
|
||||
rafId = requestAnimationFrame(tickFreeScroll)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user