vue红包雨实现
Vue 红包雨实现方法
核心思路
红包雨效果主要通过动态生成红包元素、控制下落动画、碰撞检测和点击交互实现。Vue的响应式特性适合管理红包状态,结合CSS动画或JavaScript动画库完成效果。
实现步骤
1. 红包元素生成
- 使用
v-for动态渲染红包DOM,每个红包对象包含位置、速度、状态等属性。data() { return { redPackets: [], config: { maxCount: 50, // 最大红包数 speedRange: [2,5], // 下落速度范围 widthRange: [30,60] // 红包宽度范围 } } }, methods: { generatePacket() { return { id: Date.now() + Math.random(), x: Math.random() * window.innerWidth, y: -50, speed: this.getRandomSpeed(), width: this.getRandomWidth(), clicked: false } }, getRandomSpeed() { const [min, max] = this.config.speedRange return min + Math.random() * (max - min) } }
2. 动画控制
- 使用
requestAnimationFrame或CSS@keyframes实现平滑下落:animate() { this.redPackets.forEach(packet => { if (!packet.clicked) { packet.y += packet.speed if (packet.y > window.innerHeight) { packet.y = -50 packet.x = Math.random() * window.innerWidth } } }) this.animationId = requestAnimationFrame(this.animate) }
3. 点击交互
- 绑定点击事件处理红包消失和奖励逻辑:
<div v-for="packet in redPackets" :key="packet.id" class="red-packet" :style="{ left: `${packet.x}px`, top: `${packet.y}px`, width: `${packet.width}px` }" @click="onPacketClick(packet)" ></div>
4. 性能优化
- 使用
transform: translate代替top/left布局 - 限制同时显示的红包数量
- 回收屏幕外的红包对象
完整示例代码
<template>
<div class="container">
<div
v-for="packet in activePackets"
:key="packet.id"
class="red-packet"
:style="packetStyle(packet)"
@click="handleClick(packet)"
>
<span class="amount" v-if="packet.clicked">+{{ packet.amount }}</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
packets: [],
config: {
spawnInterval: 300,
maxCount: 30,
speedRange: [3, 8],
sizeRange: [40, 80]
}
}
},
computed: {
activePackets() {
return this.packets.filter(p => !p.clicked || p.animateOut)
}
},
methods: {
packetStyle(packet) {
return {
transform: `translate(${packet.x}px, ${packet.y}px)`,
width: `${packet.size}px`,
height: `${packet.size}px`,
opacity: packet.clicked ? 0 : 1,
transition: packet.clicked ? 'all 0.5s ease-out' : ''
}
},
spawnPacket() {
if (this.packets.length < this.config.maxCount) {
this.packets.push({
id: Date.now(),
x: Math.random() * (window.innerWidth - 100),
y: -100,
speed: this.config.speedRange[0] +
Math.random() * (this.config.speedRange[1] - this.config.speedRange[0]),
size: this.config.sizeRange[0] +
Math.random() * (this.config.sizeRange[1] - this.config.sizeRange[0]),
amount: Math.floor(Math.random() * 100),
clicked: false
})
}
},
updatePositions() {
this.packets.forEach(packet => {
if (!packet.clicked) {
packet.y += packet.speed
if (packet.y > window.innerHeight) {
packet.y = -100
packet.x = Math.random() * (window.innerWidth - 100)
}
}
})
},
handleClick(packet) {
if (!packet.clicked) {
packet.clicked = true
setTimeout(() => {
this.packets = this.packets.filter(p => p.id !== packet.id)
}, 500)
}
}
},
mounted() {
setInterval(this.spawnPacket, this.config.spawnInterval)
setInterval(this.updatePositions, 16)
}
}
</script>
<style>
.red-packet {
position: absolute;
background: url('red-packet.png') center/contain no-repeat;
cursor: pointer;
z-index: 10;
}
.amount {
position: absolute;
color: gold;
font-weight: bold;
animation: float-up 1s forwards;
}
@keyframes float-up {
to { transform: translateY(-50px); opacity: 0; }
}
</style>
高级优化方向
- 使用Web Workers处理大量红包计算
- 实现3D倾斜效果增加立体感
- 添加背景粒子效果增强视觉冲击
- 引入物理引擎实现碰撞反弹
通过调整生成频率、下落速度和红包样式参数,可以创建不同难度的红包雨效果。实际开发中建议使用GSAP等专业动画库处理复杂动画序列。







