vue+实现弹幕
实现弹幕的基本思路
弹幕功能的实现需要结合DOM操作、动画控制和数据管理。Vue的响应式特性和组件化开发能有效简化弹幕逻辑的实现。
弹幕数据管理
使用Vue的data或ref(Composition API)存储弹幕消息数组,每条消息包含文本、颜色、位置等信息:
// Options API
data() {
return {
danmus: [],
colors: ['#ff0000', '#00ff00', '#0000ff', '#ffff00']
}
}
// Composition API
const danmus = ref([])
const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00']
弹幕容器与样式
创建固定定位的容器作为弹幕显示区域,设置overflow: hidden防止页面滚动:
<div class="danmu-container" ref="container">
<div
v-for="(item, index) in danmus"
:key="index"
class="danmu-item"
:style="{
color: item.color,
top: item.top + 'px',
left: item.left + 'px'
}"
>
{{ item.text }}
</div>
</div>
.danmu-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
overflow: hidden;
}
.danmu-item {
position: absolute;
white-space: nowrap;
font-size: 24px;
text-shadow: 1px 1px 2px #000;
}
弹幕动画控制
使用CSS动画或requestAnimationFrame实现移动效果。CSS动画方案更简单:
addDanmu(text) {
const containerWidth = this.$refs.container.offsetWidth
const containerHeight = this.$refs.container.offsetHeight
const top = Math.random() * containerHeight * 0.8
this.danmus.push({
text,
color: this.colors[Math.floor(Math.random() * this.colors.length)],
top,
left: containerWidth
})
setTimeout(() => {
this.danmus.shift()
}, 10000) // 根据动画持续时间清理数据
}
弹幕发送功能
添加输入框和发送按钮,触发弹幕添加:
<div class="danmu-input">
<input v-model="inputText" @keyup.enter="sendDanmu" />
<button @click="sendDanmu">发送</button>
</div>
sendDanmu() {
if (!this.inputText.trim()) return
this.addDanmu(this.inputText)
this.inputText = ''
}
性能优化
对于大量弹幕,使用虚拟滚动或对象池技术优化性能:
cleanDanmus() {
// 移除屏幕外的弹幕
this.danmus = this.danmus.filter(item => {
const element = document.querySelector(`.danmu-item:nth-child(${item.id})`)
if (!element) return false
const rect = element.getBoundingClientRect()
return rect.right > 0
})
}
完整示例代码
组合上述代码的完整组件实现:
<template>
<div>
<div class="danmu-container" ref="container">
<div
v-for="(item, index) in danmus"
:key="index"
class="danmu-item"
:style="{
color: item.color,
top: item.top + 'px',
animation: `move ${item.duration}s linear forwards`
}"
>
{{ item.text }}
</div>
</div>
<div class="danmu-input">
<input v-model="inputText" @keyup.enter="sendDanmu" />
<button @click="sendDanmu">发送</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
danmus: [],
colors: ['#ff0000', '#00ff00', '#0000ff', '#ffff00'],
inputText: '',
duration: 10
}
},
methods: {
sendDanmu() {
if (!this.inputText.trim()) return
this.addDanmu(this.inputText)
this.inputText = ''
},
addDanmu(text) {
const containerHeight = this.$refs.container.offsetHeight
const top = Math.random() * containerHeight * 0.8
this.danmus.push({
text,
color: this.colors[Math.floor(Math.random() * this.colors.length)],
top,
duration: this.duration
})
}
}
}
</script>
<style>
@keyframes move {
from { transform: translateX(100%); }
to { transform: translateX(-100%); }
}
</style>






