抽奖动画 - 十二宫格抽奖

本文介绍一种12宫格抽奖,这种抽奖方式是九宫格抽奖的演变,只不过开始播放的时候是随机方式,不是顺时针播放了。

1.需求

先看看高保,如下图1

image


图1

用户点击"立即抽奖"后12个奖品随机高亮

请求接口,待所有产品都高亮后,根据接口结果,固定在抽中奖品上

最后弹出中奖结果弹框

2.思路 2.1 高亮

实现图片的高亮有很多种方式,上一篇九宫格抽奖中使用的是修改图片容器的背景色,这里也可以让UI同事涉及两套图片,一套是普通显示的图片,一套是高亮显示的,这样只要使用vue动态属性来切换就可以了。

2.2 随机闪烁

随机闪烁需要用到随机数组,可以先得到奖品数据的下标数组,然后随机打乱这个数组得到混乱的下标,最后遍历数组查找对应的下标,切换高亮属性。

2.3 定时器

最后,要看到闪烁的结果,不能直接遍历数组,需要一个定时器,我们这里依然使用定时任务+async的方式实现,具体方式在下面实现过程步骤中详细介绍。

3.实现过程 3.1 奖品数据

按照高保给的顺序定义奖品数组,注意数组设置一个active属性,表示当前奖品是否高亮。代码如下:

prizes: [ {active: false, prizeName: '华为智能手环4', imgName: '1-huawei'}, {active: false, prizeName: '米家声波电动牙刷T300', imgName: '1-mijia'}, {active: false, prizeName: 'AX1800千兆双频路由器', imgName: '1-router'}, {active: false, prizeName: 'vivo TWS Neo耳机', imgName: '1-100m'}, {active: false, prizeName: 'OPPO w31真无线耳机', imgName: '1-oppo_w31'}, {active: false, prizeName: 'vivo Watch手表', imgName: '1-200m'}, {active: false, prizeName: 'reno4智能手机', imgName: '1-10y'}, {active: false, prizeName: '华为智能手表', imgName: '1-1g'}, {active: false, prizeName: 'vivo X5 Pro', imgName: '1-20g'}, {active: false, prizeName: 'vivo TWS Neo耳机', imgName: '1-vivo_neo'}, {active: false, prizeName: '小米10智能手机', imgName: '1-100y'}, {active: false, prizeName: 'vivo X50 Pro', imgName: '1-2g'} ] 3.2 高亮

这里UI提供了12个奖品图片对应的高亮图片,只要切换成高亮的图片就可以了,这个使用vue动态属性很容易实现。图片风格由UI同事负责设计,在这里要区分当图片的选中状态,我们在原图片名字后面加上后缀“_on”来区分选中图片,如下图2

image


图2

3.3 随机数组

有了上面的奖品数据,可以很容得到下标数组,然后要打断这个数组,得到一个随机数字数组。这里使用了洗牌算法来打乱数组,方法如下:

//随机排列数,洗牌算法 shuffle(arr) { let i = arr.length, t, j while (i) { j = Math.floor(Math.random() * (i--)) t = arr[i] arr[i] = arr[j] arr[j] = t } }

调用方式如下:

let arr = Array(this.prizes.length).fill(0).map((i, index) => index) console.log("打乱前的数组:", arr) //随机打乱数组元素 this.shuffle(arr) console.log("打乱后的数组", arr)

结果如下图3

image


图3

3.4 定时器&异步事件

这里使用一个定时器来执行延迟,定时器在一个延迟时间结束后再执行一个事件,这样这个事件就是一个异步事件了。

然后使用async/await把异步任务串起来,使它们按照一定的顺序来执行。代码如下:

let arr = Array(this.prizes.length).fill(0).map((i, index) => index) let timeoutID = null //模拟定时器 let sleep = time => new Promise((resolve) => { timeoutID = setTimeout(resolve, time) }) //定时任务函数,async/await let collectEvent = async(count, interval) => { for (let i = 0; i < count; i++) { //等待上一个任务完成 await sleep(interval) //按照随机数显示高亮 this.prizes.forEach((p, index) => { p.active = index === arr[i] }) } } //产生随机数组 this.shuffle(arr) //加入定时任务 collectEvent(arr.length, 300).then(() => { clearTimeout(timeoutID) })

加入定时任务的时候,collectEven方法内有12个await语句,每个await后面又是一个异步任务,这样执行collectEvent的时候会等待上一个await后面的语句有了返回再执行下一个await语句。sleep()方法会再规定时间(参数interval,传值300)内执行resolve,这样每次高亮都会间隔300毫秒时间,看上去是在随机高亮。效果如下图4

image


图4
这里是随机闪烁,如果要求按照一定的顺序来闪烁,就需要按照顺序构造数组arr了。

3.5 时间间隔

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zypzsy.html