From 1c81b4f081b117a82f2f82067768339b4e09c703 Mon Sep 17 00:00:00 2001 From: 18278715334 <18278715334@163.com> Date: Mon, 8 Dec 2025 17:05:04 +0800 Subject: [PATCH] 1 --- src/components/common/DanmakuBar.vue | 52 ++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/components/common/DanmakuBar.vue b/src/components/common/DanmakuBar.vue index ce62062..0de8a01 100644 --- a/src/components/common/DanmakuBar.vue +++ b/src/components/common/DanmakuBar.vue @@ -16,7 +16,7 @@ {{ enabled ? '开启' : '关闭' }} -
+
{ isProcessing.value = true const processNext = () => { + // 如果有弹幕实体还在当前弹幕区域内,则等待其完全离开后再装载下一条 + if (hasDanmakuInside()) { + setTimeout(processNext, 300) + return + } + if (pendingQueue.value.length === 0) { isProcessing.value = false return @@ -177,8 +183,8 @@ const processPendingQueue = () => { const item = pendingQueue.value.shift() addDanmakuToQueue(item) - // 计算下一个弹幕的延迟:1.5秒 + 0-2秒随机 - const delay = 1500 + Math.random() * 2000 + // 计算下一个弹幕的延迟:1秒 + 0-1秒随机 + const delay = 1000 + Math.random() * 1000 setTimeout(() => { processNext() @@ -198,12 +204,11 @@ const checkCollision = (newDanmaku) => { const newBottom = newTop + danmakuHeight // 检查与所有活动弹幕的垂直位置碰撞 - // 由于弹幕从右侧进入,主要检查垂直位置是否重叠 for (const existingDanmaku of activeDanmakus.value) { const existingTop = existingDanmaku.top const existingBottom = existingTop + danmakuHeight - // 检查垂直位置是否太接近(考虑最小间距) + // 垂直位置是否太接近(考虑最小间距) const verticalOverlap = !(newBottom < existingTop - minVerticalGap || newTop > existingBottom + minVerticalGap) if (verticalOverlap) { @@ -268,6 +273,7 @@ const addDanmakuToQueue = (item) => { return } + // 暂存队列(保持逻辑完整,便于未来扩展) danmakuQueue.value.push(danmaku) // 如果队列中的弹幕太多,移除最旧的 @@ -275,8 +281,20 @@ const addDanmakuToQueue = (item) => { danmakuQueue.value.shift() } - // 添加到活动弹幕列表 - activeDanmakus.value.push(danmaku) + // 仅在右侧区域空闲时添加 + if (!hasDanmakuInside()) { + activeDanmakus.value.push(danmaku) + } else { + // 如果右侧区域有弹幕,稍后再尝试 + const tryAdd = () => { + if (!hasDanmakuInside()) { + activeDanmakus.value.push(danmaku) + } else { + setTimeout(tryAdd, 200) + } + } + setTimeout(tryAdd, 200) + } // 弹幕会在动画结束时通过 animationend 事件自动移除 } @@ -285,6 +303,26 @@ const addDanmakuToQueue = (item) => { const handleAnimationEnd = (id) => { // 动画结束后,弹幕已经完全移出左侧,可以安全移除 removeDanmaku(id) + // 释放占用,继续处理待排队的弹幕 + isProcessing.value = false + processPendingQueue() +} + +// 判断当前弹幕区域内是否还有弹幕实体(交叠到可视区域) +const hasDanmakuInside = () => { + if (!danmakuWrapper.value) return false + const wrapperRect = danmakuWrapper.value.getBoundingClientRect() + const elements = danmakuWrapper.value.querySelectorAll('.danmaku-item') + for (const el of elements) { + const rect = el.getBoundingClientRect() + // 判断是否与可视区域有交叠(水平和垂直都需有重叠) + const horizontalOverlap = rect.right > wrapperRect.left && rect.left < wrapperRect.right + const verticalOverlap = rect.bottom > wrapperRect.top && rect.top < wrapperRect.bottom + if (horizontalOverlap && verticalOverlap) { + return true + } + } + return false } // 计算弹幕的垂直位置(随机分散,避免重叠)