2
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="danmaku in activeDanmakus"
|
v-for="danmaku in activeDanmakus"
|
||||||
:key="danmaku.id"
|
:key="danmaku.id"
|
||||||
|
:data-danmaku-id="danmaku.id"
|
||||||
:class="['danmaku-item', `danmaku-${danmaku.status}`]"
|
:class="['danmaku-item', `danmaku-${danmaku.status}`]"
|
||||||
:style="{
|
:style="{
|
||||||
top: `${danmaku.top}px`,
|
top: `${danmaku.top}px`,
|
||||||
@@ -187,7 +188,33 @@ const processPendingQueue = () => {
|
|||||||
processNext()
|
processNext()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加弹幕到显示队列
|
// 检查弹幕碰撞(基于垂直位置和预计路径)
|
||||||
|
const checkCollision = (newDanmaku) => {
|
||||||
|
if (!danmakuWrapper.value) return false
|
||||||
|
|
||||||
|
const danmakuHeight = 40 // 弹幕高度
|
||||||
|
const minVerticalGap = 45 // 最小垂直间距(确保不重叠)
|
||||||
|
const newTop = newDanmaku.top
|
||||||
|
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) {
|
||||||
|
return true // 发生碰撞
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加弹幕到显示队列(带碰撞检测)
|
||||||
const addDanmakuToQueue = (item) => {
|
const addDanmakuToQueue = (item) => {
|
||||||
const danmaku = {
|
const danmaku = {
|
||||||
id: item.id || `danmaku-${Date.now()}-${Math.random()}`,
|
id: item.id || `danmaku-${Date.now()}-${Math.random()}`,
|
||||||
@@ -199,12 +226,48 @@ const addDanmakuToQueue = (item) => {
|
|||||||
timeAgo: calculateTimeAgo(item.start_at || item.created_at),
|
timeAgo: calculateTimeAgo(item.start_at || item.created_at),
|
||||||
top: 0,
|
top: 0,
|
||||||
duration: props.danmakuSpeed,
|
duration: props.danmakuSpeed,
|
||||||
delay: 0
|
delay: 0,
|
||||||
|
width: 0, // 将在DOM渲染后计算
|
||||||
|
currentLeft: 0 // 当前水平位置
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算垂直位置(随机分散,避免重叠)
|
// 尝试找到一个不碰撞的位置
|
||||||
|
let attempts = 0
|
||||||
|
let foundPosition = false
|
||||||
|
|
||||||
|
while (attempts < 20 && !foundPosition) {
|
||||||
|
// 计算垂直位置
|
||||||
danmaku.top = calculateTopPosition()
|
danmaku.top = calculateTopPosition()
|
||||||
|
|
||||||
|
// 检查碰撞
|
||||||
|
if (!checkCollision(danmaku)) {
|
||||||
|
foundPosition = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
attempts++
|
||||||
|
|
||||||
|
// 如果碰撞,稍微调整垂直位置
|
||||||
|
if (attempts < 10) {
|
||||||
|
// 尝试不同的垂直位置
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
// 如果多次尝试都碰撞,延迟生成
|
||||||
|
setTimeout(() => {
|
||||||
|
addDanmakuToQueue(item)
|
||||||
|
}, 500 + Math.random() * 1000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundPosition) {
|
||||||
|
// 如果找不到位置,延迟生成
|
||||||
|
setTimeout(() => {
|
||||||
|
addDanmakuToQueue(item)
|
||||||
|
}, 1000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
danmakuQueue.value.push(danmaku)
|
danmakuQueue.value.push(danmaku)
|
||||||
|
|
||||||
// 如果队列中的弹幕太多,移除最旧的
|
// 如果队列中的弹幕太多,移除最旧的
|
||||||
@@ -212,8 +275,9 @@ const addDanmakuToQueue = (item) => {
|
|||||||
danmakuQueue.value.shift()
|
danmakuQueue.value.shift()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 立即添加到活动弹幕列表
|
// 添加到活动弹幕列表
|
||||||
activeDanmakus.value.push(danmaku)
|
activeDanmakus.value.push(danmaku)
|
||||||
|
|
||||||
// 弹幕会在动画结束时通过 animationend 事件自动移除
|
// 弹幕会在动画结束时通过 animationend 事件自动移除
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,12 +412,12 @@ onUnmounted(() => {
|
|||||||
animation: danmaku-scroll linear forwards;
|
animation: danmaku-scroll linear forwards;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
transform: translateZ(0);
|
/* 弹幕从右侧隐藏区域开始(容器外),由动画控制位置 */
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes danmaku-scroll {
|
@keyframes danmaku-scroll {
|
||||||
from {
|
from {
|
||||||
transform: translateX(0);
|
transform: translateX(100%);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
|
|||||||
Reference in New Issue
Block a user