vue实现平缓弹幕
Vue实现平缓弹幕的方法
在Vue中实现平缓弹幕效果,可以通过CSS动画和Vue的动态渲染结合完成。以下是具体实现方式:
使用CSS动画控制弹幕移动
通过CSS的@keyframes定义弹幕从右到左的平移动画,结合Vue的v-for动态渲染弹幕列表。
<template>
<div class="danmu-container">
<div
v-for="(item, index) in danmuList"
:key="index"
class="danmu-item"
:style="{ top: `${item.top}px`, animationDuration: `${item.speed}s` }"
>
{{ item.text }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
danmuList: []
}
},
methods: {
addDanmu(text) {
const top = Math.random() * 200 // 随机高度
const speed = 5 + Math.random() * 5 // 随机速度
this.danmuList.push({ text, top, speed })
}
}
}
</script>
<style>
.danmu-container {
position: relative;
width: 100%;
height: 300px;
overflow: hidden;
}
.danmu-item {
position: absolute;
white-space: nowrap;
animation: danmuMove linear;
animation-fill-mode: forwards;
}
@keyframes danmuMove {
from { transform: translateX(100%); }
to { transform: translateX(-100%); }
}
</style>
使用requestAnimationFrame实现更流畅动画
对于性能要求较高的场景,可以使用JavaScript控制动画帧。
<template>
<div class="danmu-container" ref="container">
<div
v-for="(item, index) in danmuList"
:key="index"
class="danmu-item"
:style="{ top: `${item.top}px`, left: `${item.left}px` }"
>
{{ item.text }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
danmuList: [],
animationId: null
}
},
mounted() {
this.startAnimation()
},
beforeDestroy() {
cancelAnimationFrame(this.animationId)
},
methods: {
addDanmu(text) {
const top = Math.random() * 200
const speed = 1 + Math.random() * 3
this.danmuList.push({
text,
top,
speed,
left: this.$refs.container.offsetWidth
})
},
startAnimation() {
const animate = () => {
this.danmuList = this.danmuList.map(item => {
return {
...item,
left: item.left - item.speed
}
}).filter(item => item.left > -100)
this.animationId = requestAnimationFrame(animate)
}
animate()
}
}
}
</script>
使用第三方库优化性能
对于复杂弹幕场景,可以考虑使用专门的动画库如GSAP:
import { gsap } from 'gsap'
methods: {
addDanmuWithGSAP(text) {
const top = Math.random() * 200
const el = document.createElement('div')
el.className = 'danmu-item'
el.textContent = text
el.style.top = `${top}px`
this.$refs.container.appendChild(el)
gsap.fromTo(el,
{ x: this.$refs.container.offsetWidth },
{
x: -el.offsetWidth,
duration: 5,
ease: 'none',
onComplete: () => el.remove()
}
)
}
}
弹幕碰撞检测实现
为避免弹幕重叠,可以实现简单的碰撞检测:
methods: {
getSafeTop(existingItems) {
const containerHeight = this.$refs.container.offsetHeight
const itemHeight = 30 // 假设每条弹幕高度
for(let y = 0; y < containerHeight - itemHeight; y += itemHeight + 10) {
const isSafe = !existingItems.some(item =>
Math.abs(item.top - y) < itemHeight + 10 &&
item.left > -100
)
if(isSafe) return y
}
return Math.random() * containerHeight
}
}
以上方法可根据实际需求选择或组合使用,CSS动画方案适合简单场景,requestAnimationFrame提供更精细控制,而GSAP等库则能处理复杂动画需求。

