vue3

vue3.0实现弹幕

<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>
上次更新: