vue实现抽奖轮盘
实现抽奖轮盘的基本思路
使用Vue实现抽奖轮盘的核心在于动态旋转动画和结果判定。通常需要结合CSS动画或JavaScript动画库(如GSAP)控制轮盘的旋转角度,并通过随机数或后端接口确定最终奖项。

基础HTML结构
<template>
<div class="lottery-container">
<div class="wheel" :style="{ transform: `rotate(${currentAngle}deg)` }">
<div class="wheel-item" v-for="(item, index) in prizes" :key="index"
:style="{ '--item-rotate': index * sectorAngle + 'deg' }">
{{ item.name }}
</div>
</div>
<button @click="startLottery" :disabled="isRotating">开始抽奖</button>
</div>
</template>
数据与样式定义
<script>
export default {
data() {
return {
prizes: [
{ name: "奖品1", probability: 0.1 },
{ name: "奖品2", probability: 0.2 },
// ...其他奖品
],
currentAngle: 0,
isRotating: false,
sectorAngle: 360 / 8 // 假设8个奖品区域
}
}
}
</script>
<style>
.wheel {
width: 300px;
height: 300px;
border-radius: 50%;
position: relative;
transition: transform 4s cubic-bezier(0.17, 0.67, 0.12, 0.99);
background: conic-gradient(
red 0deg 45deg,
blue 45deg 90deg,
/* 其他颜色分区 */
);
}
.wheel-item {
position: absolute;
width: 50%;
height: 50%;
transform-origin: bottom right;
transform: rotate(var(--item-rotate)) translateY(-100%);
text-align: center;
}
</style>
核心旋转逻辑
methods: {
getRandomPrize() {
const random = Math.random();
let sum = 0;
for (let i = 0; i < this.prizes.length; i++) {
sum += this.prizes[i].probability;
if (random <= sum) return i;
}
return 0;
},
startLottery() {
if (this.isRotating) return;
const targetIndex = this.getRandomPrize();
const targetAngle = 3600 - (targetIndex * this.sectorAngle) + (Math.random() * 20);
this.isRotating = true;
this.currentAngle = this.currentAngle % 360;
this.currentAngle += targetAngle;
setTimeout(() => {
this.isRotating = false;
alert(`恭喜获得: ${this.prizes[targetIndex].name}`);
}, 4000);
}
}
高级优化方案
-
贝塞尔曲线优化动画 使用
cubic-bezier(0.17, 0.67, 0.12, 0.99)实现先快后慢的物理阻尼效果
-
指针固定实现 在轮盘外层添加绝对定位的指针元素:
.pointer { position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 20px; height: 20px; background: black; clip-path: polygon(50% 100%, 0 0, 100% 0); } -
Web Worker处理概率计算 对于复杂概率计算可以移交给Web Worker避免主线程阻塞
服务端集成方案
async startLottery() {
try {
const res = await axios.get('/api/lottery');
const targetAngle = 3600 - (res.data.index * this.sectorAngle);
// ...旋转逻辑
} catch (error) {
console.error(error);
}
}
注意事项
- 旋转角度计算需考虑
currentAngle % 360避免数值过大 - 移动端需要添加
touchstart事件支持 - 中奖概率总和应为1,前端可做归一化处理
- 生产环境建议将中奖判定逻辑放在服务端






