九宫格抽奖,大转盘抽奖,滚动抽奖,刮刮卡抽奖(一)

602 阅读3分钟

做了各种各样的营销抽奖活动,有九宫格抽奖、大转盘抽奖、滚动抽奖、刮刮卡抽奖,来总结一波~

九宫格抽奖
大转盘抽奖
滚动抽奖
刮刮卡抽奖

九宫格抽奖

我们先来看下最终实现的效果:

九宫格抽奖演示.gif

思路

我们需要定义九个格子,抽奖按钮放在最中间,使用flex来实现布局,摆放顺序是z字形,但是我们抽奖是顺时针转动的,所以要注意下奖品的摆放顺序。
点击抽奖的时候,我们需要请求后台接口,后台会返回给我们抽中的奖品,也就是九宫格转动最终要停下来的位置,为了让效果看起来更好看,会默认先让转盘转几圈,然后再转动到奖品位置停下。转动效果是通过定时器依次改变每个格子的背景颜色来实现的。抽奖转动效果一般是速度慢慢加快或者匀速,然后再慢慢减慢直至停止到奖品位置处。

实现

先来写静态页面:

<div id="app">
   <div class="lottery__list">
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 0}">1</div>
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 1}">2</div>
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 2}">3</div>
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 7}">8</div>
        <div class="lottery__item btn" @click="handleLottery">抽奖</div>
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 3}">4</div>
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 6}">7</div>
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 5}">6</div>
        <div class="lottery__item" :class="{'lottery__item--active':activeIndex === 4}">5</div>
    </div>
</div>

动态定义了一个lottery__item--activeclass,转动效果就是通过这个class实现的,activeIndex是当前转动到的格子的索引,转盘从第一个格子开始顺时针转动。

样式:

<style>
    .lottery__list {
        display: flex;
        flex-wrap: wrap;
        width: 184px;
        border-bottom: 1px solid #ccc;
        border-right: 1px solid #ccc;
    }

    .lottery__item {
        width: 60px;
        height: 60px;
        text-align: center;
        line-height: 60px;
        border-top: 1px solid #ccc;
        border-left: 1px solid #ccc;
    }

    .lottery__item--active {
        background-color: red;
    }

    .btn {
        cursor: pointer;
    }
</style>

vue实现:

通过上面的分析我们知道,我们需要定义好以下几个变量:最终的奖品位置、目前转动的步数、最终停下来的目标步数、转动的速度、定时器ID。

<script>
    const { createApp, reactive, toRefs, computed } = Vue
    createApp({
        setup() {
            const state = reactive({
                lottery: 0, // 奖品
                step: -1, // 目前转动的步数
                stopStep: 32, // 目标步数,上面我们有提到默认都会转几圈,这里默认转四圈,一圈有八个格子,四圈就是要转动32步
                speed: 2, // 转动速度,我们是通过定时器去实现转动效果的,所以这也就是定时器的执行频率
                timer: 0, // 定时器ID
                loading: false
            })
            // 通过目前转动的步数来对8取模得到当前转到的格子索引
            const activeIndex = computed(() => {
                return state.step % 8
            })
            // 点击抽奖之后调用的函数
            function handleLottery() {
                if(state.loading) return
                state.loading = true
                // 最终获得的奖品,实际业务中是通过接口获取的,这里使用随机数来模拟下
                state.lottery = Math.floor(Math.random() * 8)
                console.log(state.lottery)
                // 计算总共要转动的步数,转4圈后再转到奖品处
                state.stopStep = state.lottery + 32
                // 执行抽奖函数
                timer = runFn()
            }
            function runFn() {
              // 抽奖函数
            }
            return {
                ...toRefs(state),
                activeIndex,
                handleLottery
            }
        }
    }).mount('#app')
</script>

接下来来实现抽奖函数,抽奖函数最终要实现的就是通过定时器不停的去增加step直到目标步数,那速度怎么控制呢?通过改变定时器的执行时间来控制:

function runFn() {
    // 当前步数大于等于目标步数
    if (state.step >= state.stopStep) {
        // 清空定时器,停止转动
        clearTimeout(state.timer)
        // 将初始化步数为最终奖品的步数,转动速度也置为初始速度,下次才能正确转动
        state.step = state.lottery
        state.speed = 2
        state.loading = false
        alert(`恭喜获得${state.lottery + 1}号奖品`)
        return
    }
    // 转动到最后一圈时,增加speed,也就是定时器执行间隔时间变长,转动速度变慢
    if (state.step > (24 + state.lottery)) {
        state.speed++
    }
    // 抽奖函数每执行一次,当前步数加一
    state.step++
    // 重新开启定时器执行抽奖函数
    timer = setTimeout(runFn, state.speed * 30)
}

大转盘抽奖就实现拉~具体的实现还是要根据实际业务来,另外可以试试用requestAnimationFrame来替换setTimeout,优化动画效果。

下一篇来实现:大转盘抽奖