vue3自定义大转盘抽奖

先看看需求:
不抽奖的情况下转盘默认会转(插件不支持这个功能)
在这里插入图片描述
再看看这套模板(布局已经弄好,找ui切图微调即可)
在这里插入图片描述

一.搞个文件夹丢进去

copy全部

<!--
 * new page
 * @author: FuJing
 * @since: 2023-04-13
 * ches.vue
-->
<template>
    <div id="app" v-cloak>
        <div class="container">
            <div class="prize-list" ref="prizeWrap" :style="bgColor">
                <div
                    class="prize-item"
                    v-for="(item, index) in state.prizeList"
                    :key="index"
                    :style="prizeStyle(index)"
                >
                    <img :src="item.pic" alt="" />
                    <p>{{ item.name }}</p>
                </div>
            </div>
            <div
                class="cone"
                v-for="(item, index) in state.prizeList"
                :key="index"
            >
                <span v-if="imgId == index ? true : false">
                    <img :src="item.pic" alt="" />
                </span>
            </div>
        </div>
        <div class="begin" @click="start">点击开始抽奖</div>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref, reactive, computed } from 'vue'
const state = reactive({
    prizeList: [
        {
            name: '玫瑰',
            pic: 'https://img1.baidu.com/it/u=1125656938,422247900&fm=253&fmt=auto&app=120&f=JPEG'
        },
        {
            name: '手表',
            pic: 'https://img1.baidu.com/it/u=2631716577,1296460670&fm=253&fmt=auto&app=120&f=JPEG'
        },
        {
            name: '苹果',
            pic: 'https://img2.baidu.com/it/u=2611478896,137965957&fm=253&fmt=auto&app=138&f=JPEG'
        },
        {
            name: '棒棒糖',
            pic: 'https://img2.baidu.com/it/u=576980037,1655121105&fm=253&fmt=auto&app=138&f=PNG'
        }
        // {
        //     name: '娃娃',
        //     pic: 'https://img2.baidu.com/it/u=4075390137,3967712457&fm=253&fmt=auto&app=138&f=PNG'
        // },
        // {
        //     name: '木马',
        //     pic: 'https://img1.baidu.com/it/u=2434318933,2727681086&fm=253&fmt=auto&app=120&f=JPEG'
        // },
        // {
        //     name: '德芙',
        //     pic: 'https://img0.baidu.com/it/u=1378564582,2397555841&fm=253&fmt=auto&app=120&f=JPEG'
        // },
        // {
        //     name: '玫瑰',
        //     pic: 'https://img1.baidu.com/it/u=1125656938,422247900&fm=253&fmt=auto&app=120&f=JPEG'
        // }
    ], // 后台配置的奖品数据
    isRunning: false, // 是否正在抽奖
    baseRunAngle: 360 * 20, // 总共转动角度 至少5圈
    prizeId: 0 // 中奖id
})
const img = ref('')

const prizeWrap: any = ref(null)
// 平均每个奖品角度
const rotateAngle = computed(() => {
    const _degree = 360 / state.prizeList.length
    return _degree
})

// 要执行总角度数
const totalRunAngle = computed(() => {
    return (
        state.baseRunAngle +
        360 -
        state.prizeId * rotateAngle.value -
        rotateAngle.value / 2
    )
})

// 计算绘制转盘背景
const bgColor = computed(() => {
    const _len = state.prizeList.length
    const colorList = ['#c90007', '#c90007']
    let colorVal = ''
    for (let i = 0; i < _len; i++) {
        colorVal += `${colorList[i % 2]} ${rotateAngle.value * i}deg ${
            rotateAngle.value * (i + 1)
        }deg,`
    }
    return `
            background: conic-gradient(${colorVal.slice(0, -1)});
          `
})
// 每个奖品布局
const prizeStyle = computed(() => {
    const _degree = rotateAngle.value
    return (i: any) => {
        return `
              width: ${2 * 270 * Math.sin(((_degree / 2) * Math.PI) / 180)}px;
              height: 270px;
              transform: rotate(${_degree * i + _degree / 2}deg);
              transform-origin: 50% 100%;
            `
    }
})
// 开始自动旋转
onMounted(() => {
    // prizeWrap.value.style = `${bgColor.value} transform: rotate(-${
    //     rotateAngle.value / 2
    // }deg)`
    setTimeout(() => {
        prizeWrap.value.style = `
            ${bgColor.value}
            transform: rotate(${totalRunAngle.value / 2}deg);
            transition: all 500s ease;
          `
    }, 50)
})

onUnmounted(() => {
    prizeWrap.value.removeEventListener('transitionend', stopRun)
})

// 获取随机数
const getRandomNum = () => {
    const num = Math.floor(Math.random() * state.prizeList.length)
    return num
}
const startRun = () => {
    console.log(state.isRunning, totalRunAngle.value)
    // 设置动效
    prizeWrap.value.style = `
              ${bgColor.value}
              transform: rotate(${totalRunAngle.value}deg);
              transition: all 4s ease;
            `
    // 监听transition动效停止事件
    prizeWrap.value.addEventListener('transitionend', stopRun)
}
let imgId = ref(0)
const start = () => {
    const timer = setInterval(() => {
        imgId.value += 1
        imgId.value = imgId.value == state.prizeList.length ? 0 : imgId.value
        console.log(imgId.value)
    }, 200)
    console.log(state.isRunning, '-----------')

    // if (!state.isRunning) {
    state.isRunning = true
    console.log('开始抽奖,后台请求中奖奖品')
    // 请求返回的奖品编号 这里使用随机数  固定奖品地方===================
    const prizeId = getRandomNum()
    // const prizeId = 1
    console.log('中奖ID>>>', prizeId, state.prizeList[prizeId])
    state.prizeId = prizeId
    startRun()

    setTimeout(() => {
        img.value = state.prizeList[prizeId].pic
        imgId.value = prizeId
        clearInterval(timer)
    }, 3800)
    // }
}

const stopRun = (e: any) => {
    console.log(e)
    state.isRunning = false
    prizeWrap.value.style = `
            ${bgColor.value}
            transform: rotate(${totalRunAngle.value - state.baseRunAngle}deg);
          `
}
</script>

<style lang="less" scoped>
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
[v-cloak] {
    display: none;
}
.container {
    width: 710px;
    height: 710px;
    /*background: #98d3fc url('https://www.jq22.com/demo/vue-luck-draw-pdmm202010260015/img/bg.a4b976d5.png') no-repeat center / 100% 100%;*/
    /*background: conic-gradient(
       red 6deg, orange 6deg 18deg, yellow 18deg 45deg,
       green 45deg 110deg, blue 110deg 200deg, purple 200deg);*/
    margin: 0 auto;
    position: relative;
}
.prize-list {
    width: 710px;
    height: 710px;
    border-radius: 50%;
    border: 10px solid #ffd902;
    overflow: hidden;
    position: relative;
}
.prize-item {
    /*border: 2px solid red;*/
    width: 100px !important;
    height: 100px !important;
    position: absolute;
    left: 210px;
    // right: 400px;
    top: 160px;
    // 调整中间奖品的整体位置
    margin: 80px 0 0 80px;
}
.prize-item img {
    width: 300px;
    height: 80px;
    // 调整四个奖品的开合度 0 0 调整单个奖品的位置
    margin: -230px 0 0 -100px;
    display: block;
}
.prize-item p {
    color: #fff;
    font-size: 12px;
    text-align: center;
    line-height: 20px;
}
// 中间显示奖品的样式
.cone {
    position: absolute;
    width: 500px;
    height: 500px;
    border-radius: 50%;
    left: 110px;
    right: 0;
    top: 105px;
    bottom: 0;
    animation-name: scaleDraw; /*关键帧名称*/
    animation-timing-function: ease-in-out; /*动画的速度曲线*/
    animation-iteration-count: infinite; /*动画播放的次数*/
    animation-duration: 2s; /*动画所花费的时间*/

    overflow: hidden;
    img {
        width: 100%;
    }
}

@keyframes scaleDraw {
    /*定义关键帧、scaleDrew是需要绑定到选择器的关键帧名称*/
    0% {
        transform: scale(1); /*开始为原始大小*/
    }
    25% {
        transform: scale(1); /*放大1.1倍*/
    }
    50% {
        transform: scale(1);
    }
    75% {
        transform: scale(1);
    }
    100% {
        transform: scale(1);
    }
}
.btn::before {
    content: '';
    width: 41px;
    height: 39px;
    background: url('https://www.jq22.com/demo/jquerylocal201912122316/img/icon_point.png')
        no-repeat center / 100% 100%;
    position: absolute;
    left: 0;
    right: 0;
    top: -33px;
    margin: auto;
}
.imgs {
    position: absolute;
}

.begin {
    width: 400px;
    height: 100px;
    background-color: #fff;
    margin: 0 auto;
    line-height: 100px;
    text-align: center;
}
</style>

可以当组件引进去直接用
最后我的成果
在这里插入图片描述
转盘直接放背景图就好了(如果位置不对就叫ui给你调角度),以下是我使用到的切图,仅供参考。。。
![在这里插入图片描述](https://img-blog.csdnimg.cn/f0bb7dfdaef745b09c3d33c390def8cc.png
在这里插入图片描述
在这里插入图片描述
由于我装了自适应插件(viewport 方案)样式如果会错乱就自己调整噢,css地方有注释,方便大家找
如果要跟我一样装自适应插件,请参考(https://blog.csdn.net/qq_62809806/article/details/126850947?spm=1001.2014.3001.5501
如果有更好的转盘方案欢迎大伙分享噢~

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值