<template>
<div class="danmu-container">
<div
v-for="(item, index) in danmuList"
:key="index"
:style="{ top: item.top + 'px', right: item.right + 'px' }"
class="danmu-item"
>
{{ item.content }}
</div>
<input type="text" v-model="newDanmuContent" @keydown.enter="sendDanmu" />
</div>
</template>
<script setup>
const danmuList = reactive([])
const newDanmuContent = ref('')
// 发送新弹幕
function sendDanmu() {
const content = newDanmuContent.value.trim()
if (!content) {
return
}
danmuList.push({
content,
top: getRandomTop(),
right: 0
})
newDanmuContent.value = ''
}
// 随机获取顶部位置
function getRandomTop() {
const container = document.querySelector('.danmu-container')
const containerHeight = container.clientHeight
const itemHeight = 24
const maxCount = Math.floor(containerHeight / itemHeight)
const index = Math.floor(Math.random() * maxCount)
return index * itemHeight
}
// 移动弹幕并删除越界弹幕
function moveDanmu() {
const now = Date.now()
danmuList.forEach((item, index) => {
const duration = (now - item.startTime) / 1000
item.right = duration * 80 // 弹幕速度为80px/s
if (item.right >= window.innerWidth) {
danmuList.splice(index, 1)
}
})
}
// 每隔一定时间移动弹幕
setInterval(moveDanmu, 16)
// 监听弹幕列表变化,并设置弹幕开始时间
watchEffect(() => {
danmuList.slice(-1).forEach(item => {
item.startTime = Date.now()
})
})
</script>
<style lang="scss" scoped>
.danmu-container {
position: relative;
height: 200px;
overflow: hidden;
}
.danmu-item {
position: absolute;
white-space: nowrap;
font-size: 16px;
color: #000;
}
</style>