vue 实现红包雨
Vue 实现红包雨功能
红包雨是一种常见的互动游戏效果,可以通过 Vue 结合 CSS 动画和 JavaScript 实现。以下是实现红包雨的核心步骤:
数据结构设计
红包数据通常包含位置、速度、金额等信息,可使用数组存储:
data() {
return {
redPackets: [], // 红包数组
isRaining: false, // 是否正在下雨
score: 0 // 用户得分
}
}
红包生成逻辑
定时创建红包对象并推入数组:
startRain() {
this.isRaining = true
const interval = setInterval(() => {
if (!this.isRaining) {
clearInterval(interval)
return
}
this.redPackets.push({
id: Date.now() + Math.random(),
left: Math.random() * window.innerWidth,
speed: 2 + Math.random() * 3,
rotation: Math.random() * 360,
amount: Math.floor(Math.random() * 100) + 1
})
}, 300)
}
红包动画实现
使用 CSS 动画控制下落效果:
<template>
<div class="rain-container">
<div
v-for="packet in redPackets"
:key="packet.id"
class="red-packet"
:style="{
left: `${packet.left}px`,
top: `${packet.top}px`,
transform: `rotate(${packet.rotation}deg)`
}"
@click="catchPacket(packet)"
>
{{ packet.amount }}
</div>
</div>
</template>
.red-packet {
position: absolute;
width: 60px;
height: 80px;
background: url('red-packet.png') no-repeat;
background-size: contain;
cursor: pointer;
transition: top 0.1s linear;
text-align: center;
line-height: 80px;
color: white;
font-weight: bold;
user-select: none;
}
动画帧更新
使用 requestAnimationFrame 更新红包位置:
animate() {
this.redPackets.forEach(packet => {
packet.top += packet.speed
packet.rotation += 2
if (packet.top > window.innerHeight) {
this.removePacket(packet)
}
})
if (this.isRaining) {
requestAnimationFrame(this.animate)
}
}
点击事件处理
实现红包点击逻辑:

catchPacket(packet) {
this.score += packet.amount
this.removePacket(packet)
// 可以添加点击动画效果
}
性能优化
- 使用虚拟滚动优化大量红包渲染
- 移除屏幕外的红包对象
- 使用 CSS transform 代替 top/left 属性
- 节流红包生成频率
完整示例组件
export default {
data() {
return {
redPackets: [],
isRaining: false,
score: 0
}
},
methods: {
startRain() {
this.isRaining = true
this.animate()
// ...红包生成逻辑
},
stopRain() {
this.isRaining = false
},
animate() {
// ...动画逻辑
},
catchPacket(packet) {
// ...点击逻辑
}
},
beforeDestroy() {
this.stopRain()
}
}
注意事项
- 移动端需要添加 touch 事件支持
- 红包图片建议预加载
- 游戏结束后清除所有定时器和动画帧
- 可根据需求添加音效和爆炸动画效果
通过以上方法可以实现基本的红包雨效果,可根据具体需求调整动画细节和游戏规则。






