Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
stdj_h5
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Authored by
hookehuyr
2025-10-30 19:07:00 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
80044b287f19e36c3ed7a723a3606938911bd7cf
80044b28
1 parent
199ec3eb
fix(轮播): 修复新闻轮播切换时的闪烁问题并实现无缝循环
添加过渡状态检测防止快速点击导致的闪烁 实现尾部克隆技术完成无缝循环效果 优化最后一张的显示逻辑和复位处理
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
58 additions
and
13 deletions
src/views/Home.vue
src/views/Home.vue
View file @
80044b2
...
...
@@ -174,7 +174,7 @@
src="/src/assets/images/02 西园戒幢律寺三坛大戒法会/下@2x.png"
alt="下一张"
@click="nextSlide"
:class="{ disabled:
currentSlide >= maxSlide
}"
:class="{ disabled:
isTransitioning
}"
>
</div>
</div>
...
...
@@ -342,6 +342,8 @@ const viewMore = (type) => {
// 新闻轮播相关逻辑
const newsCarousel = ref(null)
const currentSlide = ref(0)
const isTransitioning = ref(false)
const hasTailClone = ref(false)
// 新闻数据
const newsItems = ref([
...
...
@@ -367,6 +369,9 @@ const newsItems = ref([
}
])
// 原始长度用于判断“最后一张”的逻辑
const initialLength = ref(newsItems.value.length)
// 计算最大滑动位置
const maxSlide = computed(() => {
return Math.max(0, newsItems.value.length - 1)
...
...
@@ -376,14 +381,39 @@ const maxSlide = computed(() => {
const prevSlide = () => {
if (currentSlide.value > 0) {
currentSlide.value--
// 离开最后一张时移除尾部克隆,避免轨道长度异常
if (hasTailClone.value && currentSlide.value < initialLength.value - 1) {
newsItems.value.pop()
hasTailClone.value = false
}
updateCarouselPosition()
}
}
// 下一张
const nextSlide = () => {
if (currentSlide.value < maxSlide.value) {
if (isTransitioning.value) return
// 若还未到原始最后一张,正常前进
if (currentSlide.value < initialLength.value - 1) {
currentSlide.value++
// 当抵达原始最后一张时,预先追加尾部克隆以填充右侧空白
if (currentSlide.value === initialLength.value - 1 && !hasTailClone.value) {
newsItems.value.push(newsItems.value[0])
hasTailClone.value = true
}
isTransitioning.value = true
attachTransitionEndOnce(false)
updateCarouselPosition()
} else {
// 处于原始最后一张:使用尾部克隆进行无缝循环
if (!hasTailClone.value) {
newsItems.value.push(newsItems.value[0])
hasTailClone.value = true
}
currentSlide.value++
isTransitioning.value = true
attachTransitionEndOnce(true)
updateCarouselPosition()
}
}
...
...
@@ -393,29 +423,44 @@ const updateCarouselPosition = () => {
const carouselEl = newsCarousel.value
if (!carouselEl) return
const containerEl = carouselEl.parentElement
const containerWidth = containerEl ? containerEl.clientWidth : 0
const firstItem = carouselEl.querySelector('.news-item')
if (!firstItem) return
const itemWidth = firstItem.getBoundingClientRect().width
// 读取gap像素值,回退到0.5rem(8px)
let gapStr = getComputedStyle(carouselEl).gap
if (!gapStr || gapStr === 'normal') {
gapStr = '8px'
}
const gapPx = parseFloat(gapStr) || 8
let distance = currentSlide.value * (itemWidth + gapPx)
const distance = currentSlide.value * (itemWidth + gapPx)
carouselEl.style.transform = `translateX(-${distance}px)`
}
// 最后一张时,保证完整显示(居中显示,无下一张时不被裁切)
if (currentSlide.value === maxSlide.value) {
const lastOffset = (newsItems.value.length - 1) * (itemWidth + gapPx)
const centerOffset = Math.max(0, (containerWidth - itemWidth) / 2)
distance = lastOffset - centerOffset
// 动画结束后复位(如处于无缝循环场景)
const attachTransitionEndOnce = (looping) => {
const el = newsCarousel.value
if (!el) {
isTransitioning.value = false
return
}
const handler = () => {
el.removeEventListener('transitionend', handler)
if (looping) {
const prevTransition = el.style.transition
el.style.transition = 'none'
// 移除临时克隆,重置到第一张
newsItems.value.pop()
hasTailClone.value = false
currentSlide.value = 0
updateCarouselPosition()
// 强制重绘后恢复过渡
void el.offsetHeight
el.style.transition = prevTransition || 'transform 0.3s ease'
}
isTransitioning.value = false
}
carouselEl.style.transform = `translateX(-${distance}px)`
el.addEventListener('transitionend', handler)
}
// 处理新闻点击事件
...
...
Please
register
or
login
to post a comment