弹幕
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
animationDuration: `${danmaku.duration}ms`,
|
||||
animationDelay: `${danmaku.delay}ms`
|
||||
}"
|
||||
@animationend="handleAnimationEnd(danmaku.id)"
|
||||
>
|
||||
<div :class="['danmaku-content', `danmaku-content-${danmaku.status}`]">
|
||||
<span :class="['company-name', `company-name-${danmaku.status}`]">{{ danmaku.companyName || '未知企业' }}</span>
|
||||
@@ -154,13 +155,14 @@ const addDanmakuToQueue = (item) => {
|
||||
startAt: item.start_at || item.created_at,
|
||||
timeAgo: calculateTimeAgo(item.start_at || item.created_at),
|
||||
top: 0,
|
||||
duration: props.danmakuSpeed,
|
||||
duration: 0, // 将在添加到DOM后计算
|
||||
delay: 0
|
||||
}
|
||||
|
||||
// 计算垂直位置(避免重叠)
|
||||
// 计算垂直位置(随机分散,避免重叠)
|
||||
danmaku.top = calculateTopPosition()
|
||||
danmaku.delay = Math.random() * 500 // 随机延迟0-500ms,让弹幕错开
|
||||
// 增加随机延迟,让弹幕错开时间出现(0-2000ms)
|
||||
danmaku.delay = Math.random() * 2000
|
||||
|
||||
danmakuQueue.value.push(danmaku)
|
||||
|
||||
@@ -169,41 +171,66 @@ const addDanmakuToQueue = (item) => {
|
||||
danmakuQueue.value.shift()
|
||||
}
|
||||
|
||||
// 添加到活动弹幕列表
|
||||
activeDanmakus.value.push(danmaku)
|
||||
|
||||
// 弹幕动画结束后移除
|
||||
// 延迟添加弹幕,让它们错开时间出现
|
||||
setTimeout(() => {
|
||||
removeDanmaku(danmaku.id)
|
||||
}, danmaku.duration + danmaku.delay + 1000)
|
||||
// 使用固定的动画时间,确保弹幕完全移出左侧
|
||||
// translateX(-200%) 意味着向左移动自身宽度的200%,应该足够移出容器
|
||||
danmaku.duration = props.danmakuSpeed
|
||||
|
||||
activeDanmakus.value.push(danmaku)
|
||||
// 弹幕会在动画结束时通过 animationend 事件自动移除
|
||||
}, danmaku.delay)
|
||||
}
|
||||
|
||||
// 计算弹幕的垂直位置(只显示两行,垂直居中)
|
||||
// 处理动画结束事件
|
||||
const handleAnimationEnd = (id) => {
|
||||
// 动画结束后,弹幕已经完全移出左侧,可以安全移除
|
||||
removeDanmaku(id)
|
||||
}
|
||||
|
||||
// 计算弹幕的垂直位置(随机分散,避免重叠)
|
||||
const calculateTopPosition = () => {
|
||||
const maxLines = 2 // 最多显示两行
|
||||
const containerHeight = 80 // 容器高度80px
|
||||
const lineHeight = 40 // 每行高度40px
|
||||
const totalHeight = maxLines * lineHeight // 两行总高度80px
|
||||
const startTop = (containerHeight - totalHeight) / 2 // 垂直居中起始位置
|
||||
const minTop = 10 // 最小顶部距离
|
||||
const maxTop = containerHeight - 40 // 最大顶部距离(留出弹幕高度空间)
|
||||
|
||||
// 计算当前有多少条弹幕
|
||||
const currentCount = activeDanmakus.value.length
|
||||
// 获取当前活动的弹幕位置
|
||||
const activePositions = activeDanmakus.value.map(d => d.top).filter(pos => pos > 0)
|
||||
|
||||
// 如果已经有两条或更多,移除最旧的,保持在两行
|
||||
if (currentCount >= maxLines) {
|
||||
// 移除最旧的弹幕
|
||||
const oldestDanmaku = activeDanmakus.value[0]
|
||||
if (oldestDanmaku) {
|
||||
removeDanmaku(oldestDanmaku.id)
|
||||
// 尝试找到一个不重叠的位置
|
||||
let newTop
|
||||
let attempts = 0
|
||||
const minGap = 35 // 最小间距35px
|
||||
|
||||
do {
|
||||
// 在容器高度范围内随机生成位置
|
||||
newTop = minTop + Math.random() * (maxTop - minTop)
|
||||
attempts++
|
||||
|
||||
// 检查是否与现有弹幕重叠
|
||||
const tooClose = activePositions.some(pos => Math.abs(pos - newTop) < minGap)
|
||||
|
||||
if (!tooClose || attempts > 10) {
|
||||
break
|
||||
}
|
||||
} while (attempts < 10)
|
||||
|
||||
// 如果尝试10次还是重叠,就使用一个固定但分散的位置
|
||||
if (attempts >= 10) {
|
||||
const positions = [20, 50] // 两行固定位置
|
||||
const usedPositions = activePositions.filter(pos =>
|
||||
positions.some(fixedPos => Math.abs(pos - fixedPos) < minGap)
|
||||
)
|
||||
if (usedPositions.length < positions.length) {
|
||||
newTop = positions.find(pos =>
|
||||
!activePositions.some(used => Math.abs(used - pos) < minGap)
|
||||
) || positions[0]
|
||||
} else {
|
||||
newTop = minTop + Math.random() * (maxTop - minTop)
|
||||
}
|
||||
}
|
||||
|
||||
// 计算新弹幕的位置(两行垂直居中)
|
||||
if (activeDanmakus.value.length === 0) {
|
||||
return startTop // 第一条从居中位置开始
|
||||
} else {
|
||||
return startTop + lineHeight // 第二条在下一行
|
||||
}
|
||||
return Math.round(newTop)
|
||||
}
|
||||
|
||||
// 移除弹幕
|
||||
@@ -295,7 +322,7 @@ onUnmounted(() => {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
transform: translateX(-200%);
|
||||
transform: translateX(-300%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user