vue实现抽奖轮盘
Vue 抽奖轮盘实现方法
基础结构搭建
使用 Vue 的 transition 和 transform 实现旋转动画,核心是通过 CSS 控制旋转角度。HTML 部分需要定义轮盘容器和抽奖按钮:
<template>
<div class="wheel-container">
<div class="wheel" :style="{ transform: `rotate(${rotateDegree}deg)` }">
<!-- 奖品区块 -->
<div v-for="(item, index) in prizes" :key="index" class="prize-sector"></div>
</div>
<button @click="startLottery">开始抽奖</button>
</div>
</template>
数据与样式配置
奖品数据建议用数组存储,每个奖品对应一个扇形区域。CSS 使用 transform-origin 和 rotate 划分扇形:
data() {
return {
prizes: ['奖品1', '奖品2', '奖品3', '奖品4', '奖品5', '奖品6'],
rotateDegree: 0,
currentRotation: 0
}
}
.wheel {
width: 300px;
height: 300px;
border-radius: 50%;
position: relative;
transition: transform 4s cubic-bezier(0.17, 0.67, 0.12, 0.99);
}
.prize-sector {
position: absolute;
width: 150px;
height: 150px;
left: 50%;
top: 0;
transform-origin: left bottom;
}
旋转逻辑实现
通过计算目标角度实现减速动画效果,使用 setTimeout 控制停止位置:
methods: {
startLottery() {
const target = Math.floor(Math.random() * 6); // 随机选择奖品
const sectorAngle = 360 / this.prizes.length;
const targetDegree = 360 * 5 - target * sectorAngle; // 多转5圈后停止
this.rotateDegree = this.currentRotation + targetDegree;
this.currentRotation = this.rotateDegree % 360;
setTimeout(() => {
alert(`恭喜获得:${this.prizes[target]}`);
}, 4000);
}
}
扇形绘制优化
使用 CSS 变量动态计算每个扇形的旋转角度,确保均匀分布:
.prize-sector {
background: hsl(calc(360 / var(--total) * var(--index)), 70%, 50%);
transform: rotate(calc(360deg / var(--total) * var(--index)))
skewY(calc(90deg - 360deg / var(--total)));
}
<div v-for="(item, index) in prizes" :key="index" class="prize-sector"
:style="{
'--total': prizes.length,
'--index': index
}"></div>
指针与结果判定
添加固定指针元素,通过数学计算确定最终奖品:
// 在抽奖结束后计算实际停止位置
const normalizedDegree = this.currentRotation % 360;
const prizeIndex = Math.floor(
(360 - normalizedDegree) / (360 / this.prizes.length)
) % this.prizes.length;
性能优化建议
对于复杂动画,建议使用 requestAnimationFrame 代替 CSS 过渡。可引入 GSAP 等动画库实现更流畅的效果:
import gsap from 'gsap';
// 替换原来的 rotateDegree 赋值
gsap.to(this, {
duration: 4,
ease: "power2.out",
currentRotation: targetDegree,
onUpdate: () => {
this.rotateDegree = this.currentRotation;
}
});






