vue 实现弹幕js
在Vue中实现弹幕功能,可以通过动态渲染DOM元素并结合CSS动画或JavaScript定时器实现。以下是两种常见的实现方法:

基于CSS动画的实现
创建一个弹幕组件,利用CSS的@keyframes实现横向移动效果:

<template>
<div class="danmu-container">
<div
v-for="(item, index) in danmuList"
:key="index"
class="danmu-item"
:style="{ top: item.top + 'px', animationDuration: item.duration + 's' }"
>
{{ item.text }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
danmuList: []
}
},
methods: {
addDanmu(text) {
const height = 30 // 每条弹幕高度
const top = Math.floor(Math.random() * (300 - height)) // 随机位置
const duration = 5 + Math.random() * 5 // 随机速度
this.danmuList.push({ text, top, duration })
// 动画结束后移除
setTimeout(() => {
this.danmuList.shift()
}, duration * 1000)
}
}
}
</script>
<style>
.danmu-container {
position: relative;
width: 100%;
height: 300px;
overflow: hidden;
}
.danmu-item {
position: absolute;
white-space: nowrap;
animation: danmuMove linear;
color: #fff;
text-shadow: 1px 1px 2px #000;
}
@keyframes danmuMove {
from { transform: translateX(100%); }
to { transform: translateX(-100%); }
}
</style>
基于JavaScript定时器的实现
使用requestAnimationFrame实现更精确的弹幕控制:
<template>
<div class="danmu-container" ref="container">
<div
v-for="(item, index) in activeDanmu"
:key="index"
class="danmu-item"
:style="{ top: item.top + 'px', left: item.left + 'px' }"
>
{{ item.text }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
danmuQueue: [],
activeDanmu: [],
animationId: null
}
},
mounted() {
this.startAnimation()
},
beforeDestroy() {
cancelAnimationFrame(this.animationId)
},
methods: {
addDanmu(text) {
const height = 30
const top = Math.floor(Math.random() * (300 - height))
const speed = 2 + Math.random() * 3
this.danmuQueue.push({
text,
top,
speed,
left: this.$refs.container.offsetWidth,
width: this.calculateTextWidth(text)
})
},
calculateTextWidth(text) {
const span = document.createElement('span')
span.style.visibility = 'hidden'
span.style.whiteSpace = 'nowrap'
span.innerText = text
document.body.appendChild(span)
const width = span.offsetWidth
document.body.removeChild(span)
return width
},
startAnimation() {
const animate = () => {
// 处理队列中的新弹幕
if (this.danmuQueue.length > 0) {
this.activeDanmu.push(...this.danmuQueue)
this.danmuQueue = []
}
// 更新所有活跃弹幕位置
this.activeDanmu = this.activeDanmu.map(item => {
return {
...item,
left: item.left - item.speed
}
}).filter(item => item.left + item.width > 0)
this.animationId = requestAnimationFrame(animate)
}
animate()
}
}
}
</script>
性能优化建议
对于大量弹幕场景,考虑使用Canvas渲染代替DOM操作:
export default {
mounted() {
this.initCanvas()
this.startDraw()
},
methods: {
initCanvas() {
this.canvas = this.$refs.canvas
this.ctx = this.canvas.getContext('2d')
this.canvas.width = this.canvas.offsetWidth
this.canvas.height = this.canvas.offsetHeight
},
drawDanmu() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.activeDanmu.forEach(item => {
this.ctx.fillStyle = item.color || '#fff'
this.ctx.font = '16px sans-serif'
this.ctx.fillText(item.text, item.x, item.y)
item.x -= item.speed
})
this.activeDanmu = this.activeDanmu.filter(item => item.x + item.width > 0)
},
startDraw() {
const animate = () => {
this.drawDanmu()
this.animationId = requestAnimationFrame(animate)
}
animate()
}
}
}
功能扩展方向
- 弹幕碰撞检测:计算每条弹幕的宽度和位置,避免重叠
- 弹幕样式自定义:支持颜色、大小、字体等样式配置
- 弹幕互动:实现点击暂停、屏蔽特定用户弹幕等功能
- 弹幕池管理:控制同时显示的弹幕数量,避免性能问题
以上实现可以根据具体需求调整参数,如弹幕速度、出现频率、显示区域等。Canvas版本性能更好但实现复杂度较高,DOM版本更易扩展样式和交互功能。






