最近工作中有个9宫格抽奖的需求,一开始没啥思绪,网上查阅一番,自己又修改了一下,希望与大家交流分享。
先看一下效果图
整理一下思路
利用flex布局形成9宫格,每个格子的序号为0~8,创建一个记录当前指针的变量,点击抽奖,指正转动,当index等于变量的时候让当前格子与其他格子样式不一致,当请求后台有结果时,让指针等于结果值。
上图中黑色数组代表奖品元素排列的顺序,其中4为抽奖按钮,红色数字则为指针转动的路线。
上代码:
首先定义几个变量
constructor (props) {
super(props)
this.state = {
timer1: '', // 定时器1 快速旋转
timer2: '', // 定时器2 慢速旋转
prizeIndex: 0, // 转动指针
stopIndex: null, // 抽中奖品
arrNum: [0, 1, 2, 5, 8, 7, 6, 3], // 转动顺序
luckList: [], // 奖品集合
isRolling: false // 是否正在抽奖
}
// 这边绑定是必要的,这样 `this` 才能在回调函数中使用
this.drawPrize = this.drawPrize.bind(this);
this.move = this.move.bind(this);
this.lowSpeed = this.lowSpeed.bind(this);
}
复制代码
然后根据数据写DOM渲染的条件
因为后台返回数据只有8条奖品,所以再获取奖品集合时对数据做一些改变,这个根据实际情况而定
res.data.dtls.splice(4, 0, {prizeName: "抽奖按钮", type: 0});
复制代码
这里利用type属性对奖品和抽奖按钮做区分
renderLi = () => {
let {luckList} = this.state;
return luckList.map((list, index) => {
if (list.type !== 0) {
return
{list.type===1||list.type===2?
:
list.type===3?
: ""
}
} else {
return
}
})
}
复制代码
{this.renderLi()}
复制代码
点击抽奖按钮运行函数drawPrize
// 点击抽奖 执行快速转动,2秒后执行慢速转动
async drawPrize() {
if (!this.state.isRolling) {
this.setState({
prizeIndex: 0,
stopIndex: null,
isRolling: true,
timer1: setInterval(this.move, 100)
});
setTimeout(() => { //转一圈半之后降速
clearInterval(this.state.timer1);
this.lowSpeed()
}, 2000)
}
}
复制代码
慢速转动
lowSpeed() {//慢速转动
// 先清除快速转动的定时器
clearInterval(this.state.timer1);
// 请求接口,获取转动结果
api.lotteryId(this.state.lotteryId, token).then(res => {
if(res.resultCode === '0') {
let stopIndex = null
// 对转动结果做处理
switch (res.data) {
case 4:
stopIndex = 3
break;
case 7:
stopIndex = 4
break;
case 6:
stopIndex = 5
break;
case 5:
stopIndex = 6
break;
case 3:
stopIndex = 7
break;
case 0:
stopIndex = 0
break;
case 1:
stopIndex = 1
break;
case 2:
stopIndex = 2
break;
default:
stopIndex = null
break
}
// 得到结果再起调用move函数,速度降低
this.setState({
stopIndex: stopIndex,
timer2: setInterval(this.move, 300)
});
}
}
复制代码
执行转动函数move
move() {//转动
let luckList = this.state.luckList
let arrNum = this.state.arrNum
// chose=1为转动到位置,0为正常位置
luckList[arrNum[this.state.prizeIndex]].chose = 1
luckList[arrNum[this.state.prizeIndex-1<0?7:this.state.prizeIndex-1]].chose = 0
// 如果指针位置prizeIndex与结果位置相同,则抽奖完成,清除所有定时器
if (this.state.stopIndex !== null && (this.state.prizeIndex === this.state.stopIndex)) {
clearInterval(this.state.timer1);
clearInterval(this.state.timer2);
setTimeout(() => {
this.setState({
isRolling: false // 可以继续抽奖
})
}, 300);
}
// 否则,继续转动,这里需要对零界位置做一下处理
else {
this.setState({
prizeIndex: this.state.prizeIndex + 1 === 8 ? 0 : this.state.prizeIndex + 1
})
}
}
复制代码
另外需要在第二次点击时恢复状态值,我是在其他条件下做的处理,这个根据实际情况而定。
好了,一个简单的9宫格抽奖就完成了,有更好的,更丰富的方案的请不吝赐教。