当前位置:首页 > VUE

vue弹幕实现不重叠

2026-02-25 20:07:49VUE

实现 Vue 弹幕不重叠的核心思路

弹幕不重叠的关键在于动态计算每条弹幕的垂直位置,确保新弹幕与已有弹幕在运动轨迹上不发生碰撞。可以通过轨道管理、实时碰撞检测或固定轨道分配来实现。

基于轨道分配的实现方案

轨道预计算 将屏幕垂直方向划分为若干虚拟轨道,每条弹幕在固定轨道上运动。初始化时创建轨道状态数组,记录每个轨道是否被占用。

data() {
  return {
    tracks: 5, // 轨道数量
    trackStatus: Array(5).fill(false), // 轨道占用状态
    danmus: [] // 弹幕数据
  }
}

轨道分配算法 新弹幕生成时遍历轨道状态,找到第一个空闲轨道并标记为占用。弹幕离开屏幕后释放轨道。

methods: {
  addDanmu(text) {
    const trackIndex = this.trackStatus.findIndex(used => !used)
    if (trackIndex === -1) return // 无可用轨道

    this.trackStatus[trackIndex] = true
    this.danmus.push({
      text,
      track: trackIndex,
      left: '100%',
      id: Date.now()
    })
  },

  releaseTrack(trackIndex) {
    this.trackStatus[trackIndex] = false
  }
}

CSS 轨道定位 通过计算轨道位置确定弹幕的 top 值,使用 CSS 动画控制水平移动。

.danmu-item {
  position: absolute;
  white-space: nowrap;
  animation: move linear;
}

@keyframes move {
  from { transform: translateX(100%); }
  to { transform: translateX(-100%); }
}

基于动态碰撞检测的实现方案

实时位置检测 记录所有活跃弹幕的当前水平位置和宽度,新弹幕生成时计算垂直位置避免重叠。

checkCollision(newDanmu) {
  const newWidth = this.calculateWidth(newDanmu.text)
  return this.activeDanmus.some(danmu => {
    return danmu.top === newDanmu.top && 
           danmu.left + danmu.width > newDanmu.left
  })
}

动态定位调整 未找到合适位置时可延迟生成或调整弹幕速度,确保不会与现有弹幕冲突。

vue弹幕实现不重叠

findAvailableTop() {
  let top = 0
  while (top < maxHeight) {
    if (!this.checkCollision({ top, left: screenWidth })) {
      return top
    }
    top += rowHeight
  }
  return null
}

性能优化建议

  • 使用 requestAnimationFrame 替代 CSS 动画实现更精确控制
  • 对弹幕文本进行宽度预计算,避免频繁 DOM 操作
  • 设置合理的轨道数量和弹幕速度,平衡视觉效果和性能
  • 对于大量弹幕考虑虚拟滚动技术,只渲染可视区域内元素

完整示例组件

<template>
  <div class="danmu-container">
    <div 
      v-for="danmu in activeDanmus" 
      :key="danmu.id"
      class="danmu-item"
      :style="{
        top: `${danmu.track * 30}px`,
        color: danmu.color
      }"
    >
      {{ danmu.text }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tracks: 8,
      trackStatus: Array(8).fill(false),
      activeDanmus: []
    }
  },
  methods: {
    addDanmu(text, color = '#fff') {
      const track = this.findAvailableTrack()
      if (track === null) return

      const id = Date.now()
      this.activeDanmus.push({
        id,
        text,
        color,
        track
      })

      setTimeout(() => {
        this.releaseTrack(track)
        this.activeDanmus = this.activeDanmus.filter(d => d.id !== id)
      }, 10000)
    },

    findAvailableTrack() {
      return this.trackStatus.findIndex(used => !used)
    },

    releaseTrack(track) {
      this.trackStatus[track] = false
    }
  }
}
</script>

<style>
.danmu-container {
  position: relative;
  height: 240px;
  overflow: hidden;
}

.danmu-item {
  position: absolute;
  left: 100%;
  white-space: nowrap;
  animation: danmu-move 10s linear;
}

@keyframes danmu-move {
  to { transform: translateX(-100vw); }
}
</style>

标签: 弹幕vue
分享给朋友:

相关文章

vue里实现增删改查

vue里实现增删改查

在Vue中实现增删改查 数据初始化 在Vue组件的data中定义初始数据和表单绑定的变量: data() { return { items: [ { id: 1, name:…

vue实现发表

vue实现发表

Vue 实现发表功能 在 Vue 中实现发表功能通常涉及表单处理、数据绑定和网络请求。以下是实现步骤和代码示例: 表单设计与数据绑定 创建一个表单用于输入发表内容,使用 v-model 进行数据双向…

vue实现递归

vue实现递归

Vue 实现递归组件的方法 在 Vue 中实现递归组件通常用于处理树形结构数据(如菜单、评论列表、文件目录等)。以下是具体实现方法: 定义递归组件 通过 name 选项让组件可以递归调用自身: &…

vue实现缩放

vue实现缩放

Vue 实现缩放的方法 在 Vue 中实现缩放功能可以通过多种方式完成,以下是一些常见的方法: 使用 CSS transform 属性 通过 CSS 的 transform: scale() 属性可…

vue实现tag

vue实现tag

Vue 实现标签(Tag)功能 在 Vue 中实现标签(Tag)功能可以通过多种方式完成,以下是一些常见的方法和实现步骤: 使用动态组件和 v-for 通过 v-for 指令动态渲染标签列表,结合样…

vue轮询实现

vue轮询实现

Vue 轮询实现方法 在 Vue 中实现轮询可以通过以下几种方式: 使用 setInterval data() { return { pollInterval: null }…