vue抽奖代码实现
实现 Vue 抽奖功能
Vue 抽奖功能可以通过动态数据绑定和动画效果实现,以下是一个基础的抽奖轮盘实现方案。
模板部分
<template>
<div class="lottery-container">
<div class="wheel" :style="wheelStyle">
<div
v-for="(item, index) in prizes"
:key="index"
class="prize-item"
:style="getItemStyle(index)"
>
{{ item.name }}
</div>
</div>
<button @click="startLottery" :disabled="isRolling">
{{ isRolling ? '抽奖中...' : '开始抽奖' }}
</button>
</div>
</template>
脚本部分
<script>
export default {
data() {
return {
prizes: [
{ name: '一等奖', color: '#FF0000' },
{ name: '二等奖', color: '#00FF00' },
{ name: '三等奖', color: '#0000FF' },
{ name: '四等奖', color: '#FFFF00' },
{ name: '五等奖', color: '#FF00FF' },
{ name: '六等奖', color: '#00FFFF' }
],
currentAngle: 0,
isRolling: false,
resultIndex: 0
}
},
computed: {
wheelStyle() {
return {
transform: `rotate(${this.currentAngle}deg)`,
transition: this.isRolling ? 'transform 4s ease-out' : 'none'
}
}
},
methods: {
getItemStyle(index) {
const angle = 360 / this.prizes.length
return {
transform: `rotate(${angle * index}deg)`,
background: this.prizes[index].color
}
},
startLottery() {
if (this.isRolling) return
this.isRolling = true
this.resultIndex = Math.floor(Math.random() * this.prizes.length)
const targetAngle = 360 * 10 + (360 - (360 / this.prizes.length) * this.resultIndex)
this.currentAngle = targetAngle
setTimeout(() => {
this.isRolling = false
alert(`恭喜获得: ${this.prizes[this.resultIndex].name}`)
}, 4000)
}
}
}
</script>
样式部分
<style>
.lottery-container {
display: flex;
flex-direction: column;
align-items: center;
}
.wheel {
width: 300px;
height: 300px;
border-radius: 50%;
position: relative;
overflow: hidden;
margin: 20px;
}
.prize-item {
position: absolute;
width: 50%;
height: 50%;
left: 50%;
top: 0;
transform-origin: left bottom;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
button {
padding: 10px 20px;
background: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
background: #cccccc;
cursor: not-allowed;
}
</style>
九宫格抽奖实现
另一种常见的抽奖形式是九宫格抽奖,实现方式如下:
模板部分
<template>
<div class="grid-lottery">
<div
v-for="(item, index) in gridPrizes"
:key="index"
class="grid-item"
:class="{ active: activeIndex === index }"
@click="startGridLottery"
>
{{ item.name }}
</div>
</div>
</template>
脚本部分
<script>
export default {
data() {
return {
gridPrizes: [
{ name: '奖品1' }, { name: '奖品2' }, { name: '奖品3' },
{ name: '奖品8' }, { name: '开始' }, { name: '奖品4' },
{ name: '奖品7' }, { name: '奖品6' }, { name: '奖品5' }
],
activeIndex: -1,
isGridRolling: false,
speed: 100,
currentLoop: 0,
totalLoops: 2,
targetIndex: 4 // 假设最终停在奖品5
}
},
methods: {
startGridLottery() {
if (this.isGridRolling) return
this.isGridRolling = true
this.currentLoop = 0
this.targetIndex = Math.floor(Math.random() * 8)
this.moveLight()
},
moveLight() {
this.activeIndex = (this.activeIndex + 1) % 8
if (this.activeIndex === 0) {
this.currentLoop++
}
if (this.currentLoop < this.totalLoops ||
(this.currentLoop === this.totalLoops && this.activeIndex !== this.targetIndex)) {
setTimeout(this.moveLight, this.speed)
} else {
setTimeout(() => {
this.isGridRolling = false
alert(`恭喜获得: ${this.gridPrizes[this.targetIndex].name}`)
}, 500)
}
}
}
}
</script>
样式部分
<style>
.grid-lottery {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
gap: 5px;
}
.grid-item {
border: 1px solid #ddd;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.grid-item.active {
background-color: #ffeb3b;
}
</style>
注意事项
- 抽奖动画效果可以通过调整 transition 时间和缓动函数来优化
- 实际项目中应该从后端获取抽奖结果,前端只负责展示动画
- 抽奖概率应该由后端控制,避免前端被篡改
- 移动端需要考虑触摸事件的处理
- 可以添加音效增强用户体验
这些实现方案可以根据实际需求进行调整和扩展,比如添加更复杂的动画效果、支持多种抽奖模式等。







