轉盤抽獎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>