vue实现简单弹幕效果
实现基础弹幕效果
在Vue中实现弹幕效果需要结合CSS动画和动态数据渲染。以下是一个基础实现方案:
模板部分
<template>
<div class="danmu-container">
<div
v-for="(item, index) in danmuList"
:key="index"
class="danmu-item"
:style="{
top: `${item.top}px`,
color: item.color,
animationDuration: `${item.speed}s`
}"
>
{{ item.text }}
</div>
<input v-model="inputText" @keyup.enter="sendDanmu" />
</div>
</template>
脚本部分

<script>
export default {
data() {
return {
danmuList: [],
inputText: '',
colors: ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff']
}
},
methods: {
sendDanmu() {
if (!this.inputText.trim()) return
const newDanmu = {
text: this.inputText,
top: Math.random() * 200,
color: this.colors[Math.floor(Math.random() * this.colors.length)],
speed: 5 + Math.random() * 5
}
this.danmuList.push(newDanmu)
this.inputText = ''
// 移除已完成动画的弹幕
setTimeout(() => {
this.danmuList.shift()
}, newDanmu.speed * 1000)
}
}
}
</script>
样式设计
弹幕样式需要结合CSS动画实现横向移动效果:
<style>
.danmu-container {
position: relative;
width: 100%;
height: 300px;
overflow: hidden;
background: #000;
}
.danmu-item {
position: absolute;
white-space: nowrap;
font-size: 20px;
animation: danmuMove linear;
animation-fill-mode: forwards;
}
@keyframes danmuMove {
from {
transform: translateX(100%);
}
to {
transform: translateX(-100%);
}
}
</style>
优化弹幕性能
当弹幕数量较多时,需要考虑性能优化:

// 在data中添加配置
data() {
return {
maxDanmu: 50, // 最大同时显示弹幕数
// ...其他data
}
}
// 修改发送方法
sendDanmu() {
if (!this.inputText.trim()) return
// 超过最大数量时移除最早的一条
if (this.danmuList.length >= this.maxDanmu) {
this.danmuList.shift()
}
// ...原有创建弹幕逻辑
}
添加弹幕碰撞检测
防止弹幕重叠可以提高视觉效果:
methods: {
getRandomTop() {
const top = Math.random() * 200
const occupied = this.danmuList.filter(
item => Math.abs(item.top - top) < 30
).length
return occupied > 0 ? this.getRandomTop() : top
},
sendDanmu() {
// ...其他逻辑
const newDanmu = {
// ...其他属性
top: this.getRandomTop()
}
// ...后续逻辑
}
}
实现弹幕暂停功能
添加控制弹幕播放状态的交互:
<template>
<div>
<!-- ...原有内容 -->
<button @click="togglePause">{{ isPaused ? '播放' : '暂停' }}</button>
</div>
</template>
<script>
export default {
data() {
return {
isPaused: false
}
},
methods: {
togglePause() {
this.isPaused = !this.isPaused
const danmus = document.querySelectorAll('.danmu-item')
danmus.forEach(el => {
el.style.animationPlayState = this.isPaused ? 'paused' : 'running'
})
}
}
}
</script>
弹幕轨道系统
更专业的实现可以使用固定轨道:
data() {
return {
tracks: [50, 100, 150, 200], // 轨道位置
trackStatus: {} // 记录轨道占用状态
}
},
methods: {
getAvailableTrack() {
const availableTracks = this.tracks.filter(
track => !this.trackStatus[track] ||
Date.now() - this.trackStatus[track] > 3000
)
if (availableTracks.length) {
const track = availableTracks[0]
this.trackStatus[track] = Date.now()
return track
}
return this.tracks[Math.floor(Math.random() * this.tracks.length)]
}
}






