当前位置:首页 » 《关注互联网》 » 正文

前端实现转盘抽奖 - 使用 lucky-canvas 插件

14 人参与  2024年04月15日 12:58  分类 : 《关注互联网》  评论

点击全文阅读


目录

需求背景需求实现实现过程图片示意实现代码 页面效果lucky-canvas 插件官方文档

需求背景

要求实现转盘转动抽奖的功能:

只有正确率大于等于 80% 才可以进行抽奖;“谢谢参与”概率为 90%,“恭喜中奖”概率为 10%;

需求实现

在这里插入图片描述
在这里插入图片描述

实现过程图片示意

在这里插入图片描述

实现代码

安装插件

npm install @lucky-canvas/vue@latest

main.js 全局引入组件

import VueLuckyCanvas from '@lucky-canvas/vue'Vue.use(VueLuckyCanvas)

实现代码

<template>  <div class="exam-result">    <div class="info">      <div class="progress">        <nut-circleprogress            :progress="(correct / total).toFixed(1) * 100"            :is-auto="true"            color="#ff4d4f"            path-color="#ffeded"        >          <div class="progressDiv">            <div class="accuracy">正确率{{ (correct / total).toFixed(1) * 100 }}%</div>          </div>        </nut-circleprogress>      </div>    </div>    <div class="content">      <div class="result-table">        <div style="padding: 10px 10px 10px 15px">试卷分析</div>      </div>      <div class="result-table">        <div class="item">          <div class="title">题目总量:</div>          <div class="total">{{ total }}</div>          <div class="unit">题</div>        </div>      </div>      <div class="result-table">        <div class="item">          <div class="title">正确题数:</div>          <div class="correct">{{ correct }}</div>          <div class="unit">题</div>        </div>        <div class="item">          <div class="title">错误题数:</div>          <div class="error">{{ total - correct }}          </div>          <div class="unit">题</div>        </div>      </div>    </div>    <div v-if="examType === 'challenge' && (correct / total).toFixed(1) >= 0.8" class="lottery_draw_btn">恭喜您获得抽奖资格 <nut-button type="primary" size="mini" @click="toLotteryDraw">点击进行抽奖</nut-button></div>    <nut-dialog teleport="#app" :title="isShowlotteryDraw ? '点击“开始”抽奖' : ''" content="" v-model:visible="dialogVisible" customClass="task" :noCancelBtn="true" :noOkBtn="true" :closeOnClickOverlay="false">      <nut-icon name="close" @click="dialogVisible = false" />      <LuckyWheel        v-if="isShowlotteryDraw"        class="myLucky"        ref="myLuckyRef"        width="320px"        height="320px"        :prizes="prizes"        :blocks="blocks"        :buttons="buttons"        @start="startCallback"        @end="endCallback"      />      <div v-else class="result" :style="{'--color': lotteryDrawIndex === 1 ? 'red' : '#000'}">{{ lotteryDrawIndex === 1 ? "恭喜中奖" : "谢谢参与" }}</div>    </nut-dialog>  </div>  <fallback></fallback></template><script>import {  reactive, toRefs, ref, getCurrentInstance} from 'vue'import { useRoute } from 'vue-router'export default {  name: 'result',  setup() {    // const myLuckyRef = ref(null) // 【ref问题】我的代码里这种办法取不到 ref,使用 getCurrentInstance 取 ref    const instance = getCurrentInstance() // 【ref解决】使用 getCurrentInstance 取 ref    const route = useRoute()    const state = reactive({      lotteryDrawIndex: 0, // 最终转盘定格的索引      isShowlotteryDraw: true, // 是否抽奖完成      // 转盘背景配置      blocks: [{        padding: '20px',        imgs: [{          // src: 'https://img.iwave.net.cn/jeep/51c95637a377c3a12d09abe8b0f975e6.png',          src: require('@/assets/images/lottery_draw.png'),          width: 320,          height: 320,          rotate: true        }]      }],      // 每个扇形区域奖品配置      prizes: [...Array(10).keys()].map((index) => ({        fonts: [          {            text: index % 2 === 0 ? '谢谢参与' : '恭喜中奖',            top: '15%',            fontSize: '15px',            fontColor: '#ed1c24',          },        ],        background: index % 2 === 0 ? '#fff5cc' : '#e9d6e9',      })),      // 抽奖按钮配置      buttons: [        { radius: '50px', background: '#d034ac' },        { radius: '45px', background: '#fe97b2' },        {          radius: '35px',          background: '#f04a07',          pointer: true,          fonts: [{ text: '开始', top: '-10px', fontColor: '#fff' }]        }      ],      // 抽奖弹框是否展示      dialogVisible: false    })    // 获取正确题数、总题数    const { correct, total, examType } = route.query    const toLotteryDraw = () => {      state.dialogVisible = true    }    // 点击抽奖按钮会触发star回调    const startCallback = () => {      console.log('"开始抽奖"----', '开始抽奖')      // 调用抽奖组件的play方法开始游戏      // console.log('myLucky.value----', myLuckyRef.value) // 【ref问题】      // myLuckyRef.value?.play() // 【ref问题】      if (instance) {        instance.refs?.myLuckyRef?.play() // 【ref解决】      }      // this.$refs.myLucky.play()  // 【ref】vue2写法      // 模拟调用接口异步抽奖      setTimeout(() => {        // 假设index(谢谢参与90%,恭喜中奖10%)        const index = `${Math.random()}`.slice(2, 3) * 1        state.lotteryDrawIndex = index === 1 ? 1 : 2        // 调用stop停止旋转并传递中奖索引        // this.$refs.myLuckyRef.stop(index)   // 【ref】vue2写法        // myLuckyRef.value?.stop(index) // 【ref问题】        if (instance) {          instance.refs?.myLuckyRef?.stop(state.lotteryDrawIndex) // 【ref解决】        }      }, 3000)    }    // 抽奖结束会触发end回调    const endCallback = (prize) => {      console.log('"结束抽奖"----', '结束抽奖')      console.log(prize)      state.isShowlotteryDraw = false    }    return {      ...toRefs(state),      correct,      total,      examType,      toLotteryDraw,      startCallback,      endCallback    }  }}</script><style scoped lang="less">.exam-result {  .info {    margin: 0 0 5px;    padding: 10px;    background-color: white;    .progress {      display: flex;      flex-direction: column;      align-items: center;      padding: 5px;      position: relative;      .nut-circleprogress {        width: 145px !important;        height: 145px !important;        position: relative;        .progressDiv {          display: flex;          flex-direction: column;          align-items: center;          .accuracy {            color: #00000080;            background-color: #ffeded;            padding: 2px 8px;            font-size: 13px;            border-radius: 5px;          }        }      }      .circle {        position: absolute;        height: 145px;        width: 145px;        background-color: #ffeded;        border-radius: 50%;        top: 5px;        left: 50%;        transform: translate(-50%);        .circle1 {          position: absolute;          height: 115px;          width: 115px;          background-color: #ffffff;          border-radius: 50%;          top: 50%;          left: 50%;          transform: translate(-50%, -50%);        }      }    }    .count {      background-color: #fffbf3;      margin-top: 10px;      padding-top: 5px;      color: #797e79;      font-size: 14px;      display: flex;      justify-content: space-around;      .centerDiv {        display: flex;        align-items: baseline;        justify-content: center;        .number {          margin-right: 5px;          font-size: 20px;          color: #FAAD14;        }        .text {          font-size: 12px;        }      }    }  }  .content {    margin-bottom: 10px;    background: white;    border-bottom: 1px solid #dcdcdc;    .result-table {      display: flex;      font-size: 16px;      font-weight: bolder;      color: #000;      .item {        display: flex;        align-items: baseline;        border-top: 0.5px solid #dcdcdc;        flex: 1;        font-size: 16px;        padding: 10px 10px 10px 15px;        color: #7f7f7f;        font-weight: normal;        &:nth-child(2n+1) {          border-right: 0.5px solid #dcdcdc;        }        .title {          margin-right: 5px;          font-size: 14px;        }        .unit {          font-size: 12px;          margin-left: 5px;        }        .time,        .total {          color: black;          font-size: 16px;        }        .correct {          color: #04be01;          font-size: 18px;        }        .error {          color: red;          font-size: 18px;        }      }    }  }    // 弹框样式  ::v-deep .popup-center.round {    width: 90%;    .nut-dialog {      width: 100%;      padding: 20px 5px;      .nut-dialog__content {        max-height: unset;        .nut-icon-close {          position: absolute;          top: 15px;          right: 15px;        }        // 转盘结束展示结果        .result {          height: 80px;          line-height: 80px;          font-size: 20px;          font-weight: bold;          color: var(--color);        }        // 转盘        .myLucky {          display: inline-block;        }      }    }  }  // 抽奖弹框按钮  .lottery_draw_btn {    height: 25PX;    line-height: 25PX;    padding: 0 10px;    cursor: pointer;    font-size: 16px;    color: red;  }}</style>

页面效果

在这里插入图片描述
在这里插入图片描述

lucky-canvas 插件官方文档

lucky-canvas 插件官网
lucky-canvas 插件官网文档

可参考文档


点击全文阅读


本文链接:http://zhangshiyu.com/post/95522.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1