转盘抽奖demo
核心代码
class Lottery {
constructor(domId) {
this.prizeIndexArr = [0, 1, 2, 5, 8, 7, 6, 3] // 顺时针转动对应的奖品序号
this.maxStep = this.prizeIndexArr.length * 5 // 最大滚动的格子数
this.currentIndex = -1 // 当前滚动到的格子的index
this.step = 0 // 当前滚动过的格子总数
this.timer = null
this.speed = 200 // 初始速度
this.domId = domId
this.isStart = false // 是否已经开始抽奖,防止连续点击
}
doLottery = (prizeIndex) => {
if (this.isStart) {
return
}
this.startRoll(prizeIndex)
}
startRoll = (prizeIndex) => {
this.isStart = true
this.step += 1
this.currentIndex += 1
// 如果转到最后一个格子,则重置currentIndex为0,也就是从第一个格子继续转动
if (this.currentIndex > 7) {
this.currentIndex = 0
}
this.addActiveStyle()
if (this.step >= this.maxStep + this.getIndex(prizeIndex) + 1 && prizeIndex === this.prizeIndexArr[this.currentIndex]) {
clearTimeout(this.timer)
this.step = 0
this.speed = 200
this.isStart = false
} else {
this.setSpeed(prizeIndex)
this.timer = setTimeout(() => this.startRoll(prizeIndex), this.speed)
}
}
/**
* 给当前格子添加样式,取消前一个格子的样式,如果滚动到index为0的格子,则取消index为7的格子的样式
*/
addActiveStyle = () => {
const dom = document.getElementById(this.domId)
// 这里可自行设置样式
dom.children[this.prizeIndexArr[this.currentIndex]].style.background = 'yellow'
if (this.currentIndex === 0) {
dom.children[this.prizeIndexArr[7]].style.background = ''
}
if (this.currentIndex > 0) {
dom.children[this.prizeIndexArr[this.currentIndex - 1]].style.background = ''
}
}
/**
* 设置转动的速度
*/
setSpeed = (prizeIndex) => {
// 前8个格子做加速运动
if (this.step <= 8) {
this.speed -= 20
} else if (this.step >= this.maxStep + this.getIndex(prizeIndex) - 8) {
// 后9个格子做减速运动
this.speed += 60
} else {
this.speed = 40
}
}
/**
* 根据奖品的index找到prizeIndexArr对应的下标index
* @returns {number}
*/
getIndex = (prizeIndex) => {
return this.prizeIndexArr.findIndex(item => item === prizeIndex)
}
}
export default Lottery
页面使用
这里举在vue中的使用方法,react或其他原理一样
<template>
<div class="lottery">
<ul class="lottery-container" id="lottery-container">
<li v-for="item in prizeList" :key="item.id" @click="doLottery(item.id)">
{{ item.id === -1 ? "抽奖" : item.prizeName }}
</li>
</ul>
</div>
</template>
<script>
import Lottery from "@/util/lottery";
export default {
name: "lottery",
setup() {
const lottery = new Lottery("lottery-container");
const prizeList = [
{ id: 1, prizeName: "mac pro" },
{ id: 2, prizeName: "吹风机" },
{ id: 3, prizeName: "电视机" },
{ id: 4, prizeName: "冰箱" },
{ id: -1 },
{ id: 5, prizeName: "优惠券" },
{ id: 6, prizeName: "华为手机" },
{ id: 7, prizeName: "电脑" },
{ id: 8, prizeName: "笔记本" },
];
const doLottery = (id) => {
if (id !== -1) return;
const prizeIndex = Math.floor(Math.random() * 8 + 1)
lottery.doLottery(prizeIndex);
};
return {
prizeList,
doLottery,
};
},
};
</script>
<style lang="scss" scoped>
.lottery-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 3rem;
height: 3rem;
margin: 0 auto;
li {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: calc(calc(100% / 3) - 0.1rem);
height: 0.9rem;
margin: 0.05rem;
list-style: none;
border-radius: 0.04rem;
background-color: #eee;
font-size: 0.16rem;
&:nth-child(5) {
background-color: #eb6a1a;
cursor: pointer;
}
}
}
</style>