1
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
<span class="text-xs text-gray-500">{{ enabled ? '开启' : '关闭' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="danmakuWrapper" class="relative flex-1 overflow-hidden" style="min-height: 80px; max-height: 100px;">
|
||||
<div ref="danmakuWrapper" class="relative flex-1 overflow-hidden" style="min-height: 120px; max-height: 140px;">
|
||||
<div
|
||||
v-for="danmaku in activeDanmakus"
|
||||
:key="danmaku.id"
|
||||
@@ -169,6 +169,12 @@ const processPendingQueue = () => {
|
||||
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()
|
||||
}
|
||||
|
||||
// 添加到活动弹幕列表
|
||||
// 仅在右侧区域空闲时添加
|
||||
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
|
||||
}
|
||||
|
||||
// 计算弹幕的垂直位置(随机分散,避免重叠)
|
||||
|
||||
Reference in New Issue
Block a user