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

732 阅读4分钟

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

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

大转盘抽奖

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

大转盘抽奖演示.gif

思路

一般奖品都是固定的,所以UI会设计好一个有奖品的大转盘给你,但如果奖品列表是后台随机返回的,那就需要自己用css来实现大转盘。本文是通过css来实现的。 大转盘抽奖可以转动盘子,中间的指针不动;也可以转动指针,盘子不动。但是实现原理是一样的,改变旋转角度。本文实现的是转动中间的指针。

实现

先来写静态页面:

<div id="app">
    <div class="lottery__list">
        <div class="lottery__item" v-for="(item,index) in 10">
            <div class="inner">
                <span>奖品{{index + 1}}</span>
            </div>
        </div>
        <div ref="pointer" class="pointer" @click="handleLottery">开始抽奖</div>
    </div>
</div>

页面很简单,样式稍微有点复杂,大转盘是由10个扇形组成的,每个扇形的角度是36deg。我们先来看张图:

大转盘1.webp 大转盘2.jpg

一个矩形(矩形长 = 矩形宽 * 2),一个半圆形(直径 = 矩形长),半圆形和矩形对齐,然后以中心点为旋转中心开始旋转,我们可以看到半圆形和矩形相交的部分就是扇形。将矩形不设置背景色并且超出隐藏,半圆形设置背景色,半圆形旋转ndeg,就可以得到ndeg的扇形。下面我们通过代码来实现下:

// 样式
<style>
    .lottery__item {
        width: 200px;
        height: 100px;
        position: relative;
        overflow: hidden;
    }
    .inner {
        position: absolute;
        width: 200px;
        height: 100px;
        top: 100%;
        background: #ff6b6b;
        border-radius: 0 0 100px 100px;
        transform-origin: top center;
        transform: rotate(36deg);
        box-sizing: border-box;
    }
</style>

// html页面
<body>
    <div class="lottery__item">
        <div class="inner">
        </div>
    </div>
</body>

扇形已经知道了怎么实现的,接下来我们来实现大转盘:

<style>
    .lottery__list {
        position: relative;
        width: 200px;
        height: 200px;
        border: 2px solid #ff5555;
        border-radius: 50%;
    }

    .lottery__item {
        position: absolute;
        top: 0;
        left: 100px;
        width: 100px;
        height: 200px;
        overflow: hidden;
        transform-origin: left center;
    }

    .inner {
        position: absolute;
        top: 0;
        left: -100px;
        width: 100px;
        height: 200px;
        padding: 5px 3px 0 57px;
        border-radius: 100px 0 0 100px;
        transform: rotate(36deg);
        transform-origin: right center;
        font-size: 12px;
        box-sizing: border-box;
    }

    .inner span {
        display: block;
        transform-origin: center;
        transform: rotate(-19deg);
    }

    .lottery__item:nth-child(2n+1) .inner {
        background: #fef6e0;
    }

    .lottery__item:nth-child(2n) .inner {
        background: #ffffff;
    }

    .lottery__item:nth-child(1) {
        display: block;
        transform: rotate(-18deg);
    }

    .lottery__item:nth-child(2) {
        transform: rotate(18deg);
    }

    .lottery__item:nth-child(3) {
        transform: rotate(54deg);
    }

    .lottery__item:nth-child(4) {
        transform: rotate(90deg);
    }

    .lottery__item:nth-child(5) {
        transform: rotate(126deg);
    }

    .lottery__item:nth-child(6) {
        transform: rotate(162deg);
    }

    .lottery__item:nth-child(7) {
        transform: rotate(198deg);
    }

    .lottery__item:nth-child(8) {
        transform: rotate(234deg);
    }

    .lottery__item:nth-child(9) {
        transform: rotate(270deg);
    }

    .lottery__item:nth-child(10) {
        transform: rotate(306deg);
    }

    .pointer {
        position: absolute;
        left: 79px;
        top: 79px;
        width: 30px;
        height: 30px;
        padding: 6px;
        background-color: #ff5350;
        border: 1px solid #ff5350;
        border-radius: 50%;
        transition: transform 3s cubic-bezier(.2, .93, .43, 1);
        line-height: 15px;
        font-size: 12px;
        text-align: center;
    }

    .pointer::after {
        content: '';
        position: absolute;
        left: 14px;
        top: -24px;
        border-width: 12px 6px;
        border-style: solid;
        border-color: transparent;
        border-bottom-color: #ff5350;
        transform-origin: center;
    }
</style>

vue实现:

上面的样式中,我们已经给中间的指针设置了旋转动画了,所以我们需要请求后台接口拿到奖品,然后设置相应的旋转角度即可。

<script>
    const { createApp, reactive, ref, toRefs, computed, onMounted } = Vue
    createApp({
        setup() {
            const state = reactive({
                lottery: 0, // 本次抽奖的奖品索引
                lastLottery: 0, // 上一次抽奖的奖品索引
                stopDeg: 0, // 最终要旋转的角度
                loading: false
            })

            const pointer = ref()

            function handleLottery() {
                if(state.loading) return
                state.loading = true
                // 最终获得的奖品索引,实际业务中是通过接口获取的,这里使用随机数0~9来模拟下
                state.lottery = Math.floor(Math.random() * 10) 
                console.log(state.lottery)
                // 最终的旋转角度,指针指向本次奖品的旋转角度+指针从上一次的奖品指向回归0的旋转角度+ 默认转动三圈
                state.stopDeg += (state.lottery  + (10 - state.lastLottery)) * 36 + 1080
                // 旋转
                pointer.value.style.transform = `rotate(${state.stopDeg}deg)`
            }

            onMounted(() => {
                // 旋转动画结束,弹出奖品
                pointer.value.addEventListener('transitionend', () => {
                    alert(`恭喜获得奖品${state.lottery + 1}`)
                    // 保留奖品索引
                    state.lastLottery = state.lottery
                    state.loading = false
                })
            },[])

            return {
                ...toRefs(state),
                pointer,
                handleLottery
            }
        }
    }).mount('#app')
</script>

参考文章

1、30 个案例教你用纯 CSS 实现常见的几何图形
2、用CSS实现一个抽奖转盘