前端实现转盘抽奖 - 使用 lucky-canvas 插件
目录
- 需求背景
- 需求实现
- 实现过程图片示意
- 实现代码
- 页面效果
- 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" /><LuckyWheelv-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 取 refconst instance = getCurrentInstance() // 【ref解决】使用 getCurrentInstance 取 refconst 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.queryconst 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) * 1state.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 插件官网文档
可参考文档
相关文章:
前端实现转盘抽奖 - 使用 lucky-canvas 插件
目录 需求背景需求实现实现过程图片示意实现代码 页面效果lucky-canvas 插件官方文档 需求背景 要求实现转盘转动抽奖的功能: 只有正确率大于等于 80% 才可以进行抽奖;“谢谢参与”概率为 90%,“恭喜中奖”概率为 10%; 需求实现 实…...
2024.1.23力扣每日一题——最长交替子数组
2024.1.23 题目来源我的题解方法一 枚举 题目来源 力扣每日一题;题序:2765 我的题解 方法一 枚举 每次都以两个相邻作为满足要求的循环数据,并且以一个布尔变量控制循环的位置 时间复杂度:O(n) 空间复杂度:O(1) pub…...
C语言王道练习题第七周两题
第一题 Description 输入一个学生的学号,姓名,性别,用结构体存储,通过 scanf 读取后,然后再 通过 printf 打印输出 Input 学号,姓名,性别,例如输入 101 xiongda m Output 输出…...
某马头条——day11+day12
实时计算和定时计算 流式计算 kafkaStream 入门案例 导入依赖 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><exclusions><exclusion><artifactId>connect-json</artifactId&…...
springboot实现aop
目录 AOP(术语)引入依赖实现步骤测试验证感谢阅读 AOP(术语) 连接点 类里面哪些方法可以增强,这些点被称为连接点 切入点 实际被真正增强的方法 通知(增强) 实际增强的逻辑部分称为通知(增强) 通知(增强&…...
Golang 中高级工程师学习笔记
闭包的作用 闭包(Closure)是一种函数值,它可以引用在其外部定义的变量。闭包允许这些变量保持在函数内部,而不是被每次调用时重新创建。闭包的作用主要体现在以下几个方面 封装: 闭包允许函数访问其外部作用域中的变…...
USB-C接口给显示器带来怎样的变化?
随着科技的不断发展,Type-C接口已经成为现代电子设备中常见的接口标准。它不仅可以提供高速的数据传输,还可以实现快速充电和视频传输等功能。因此,使用Type-C接口的显示器方案也受到了广泛的关注。本文将介绍Type-C接口显示器的优势、应用场…...
写一份简单的产品说明书:格式和排版建议
现在的市场竞争那么激烈,拥有一份简洁明了的产品说明书可以说是很重要的。产品说明书不仅向用户提供了对产品的详细了解,还能够树立品牌形象,提升用户体验。 | 一、写一份简单的产品说明书—一些建议 1.创意封面设计 一个吸引人的封面设计能…...
【Python学习】Python学习21- 正则表达式(1)
目录 【Python学习】Python学习21- 正则表达式(1) 前言re.match函数实例 re.search方法re.match与re.search的区别参考 文章所属专区 Python学习 前言 本章节主要说明Python的正则表达式。 正则表达式是一个特殊的字符序列,它能帮助你方便的…...
Docker 和 Kubernetes:容器化时代的崛起与演变
在过去的十年间,容器化技术彻底改变了软件开发和部署的面貌。 Docker 的登场无疑是这场变革的催化剂,它将应用和服务的打包、分发、部署流程标准化,让开发者的生活变得更加简单。 紧随其后,Kubernetes 作为容器编排的领军者&#…...
美易官方京东养车回应索赔事件:推动行业健康发展并携手品牌商家加码补贴
近日,一则关于途虎养车起诉京东索赔500万元的新闻引起了业界的广泛关注。据华尔街见闻1月25日报道,针对此事,京东养车相关负责人作出了回应。京东养车表示,“震虎价”并非针对特定企业,其核心目的在于通过提升效率来改…...
深度学习与图像描述生成——看图说话(3)
目录 一、整体架构 二、学习策略 2.1 监督学习 2.2 无监督学习 2.3 强化学习 三、特征映射 3.1 定义 3.2 原理 3.3 关键技术 3.4 重要案例 3.5 特别注意下特征空间这一概念 四、语言模型 4.1 定义与原理 4.2 关键技术 4.3 重要性与作用 4.4 案例与应用 五、注…...
[SAP ABAP] ABAP编程中SY-SUBRC值的含义
在ABAP编程中,SY-SUBRC是一个系统变量,用于表示最近一次执行的系统命令(例如数据库操作、函数模块调用等)的结果状态码 SY-SUBRC的值用于检查命令是否执行成功,通常用于控制程序的流程 查询数据 使用SELECT语句选择查询 SY-SUBRC 0 &qu…...
测试模型分类
测试模型 1. 概述 软件测试和软件开发一样,都遵循软件工程原理,遵循管理学原理,所以理解好软件的开发模型会便于理解测试模型. 软件测试的一般流程: 我们发现一般的软件测试流程和软件开发的流程一样,但是这样的流程测试介入的较晚,对于前期重大的bug很难修复.所以测试的流程…...
mavros和PX4中的海拔高与椭球高转换
飞控高度传感器中一般有两种高度: 海拔高。也称AMSL(Above Mean Sea Level)height或者geoid height或者正高,顾名思义就是指高于当地平均海平面的高度。我猜气压计测得的高度应当就是与海平面相关的。椭球高。也称ellipsoid heig…...
洛谷刷题-【入门2】分支结构
目录 1.苹果和虫子 题目描述 输入格式 输出格式 输入输出样例 2.数的性质 题目描述 输入格式 输出格式 输入输出样例 3.闰年判断 题目描述 输入格式 输出格式 输入输出样例 4.apples 题目描述 输入格式 输出格式 输入输出样例 5.洛谷团队系统 题目描述 …...
文件包含技术总结
开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这中文件调用的过程一般被称为文件包含。 allow_url_fopen On(是否允许打开远程文件) allow_url_include On&…...
Docker搭建私有仓库
Docker搭建私有仓库 下载docker registry镜像 docker pull docker.io/registry2.registry镜像下载完成后,先创建一个存放镜像的目录。 mkdir -p /data/registry3.启动registry容器 docker run -itd -p 5000:5000 -v /data/registry:/var/lib/registry docker.io…...
【计算机网络】【练习题】【新加坡南洋理工大学】【Computer Control Network】
说明: 仅供学习使用。 一、题目描述 该题目描述一个网络中传播时延(Transmission Delay)的例子。题目如下: 二、问题解答(个人) 笔者第3问采用均值不等式求解。标答中采用求导数的方法求极值。似乎均值…...
【学习笔记】CF1349F2 Slime and Sequences (Hard Version)
多项式工业警告!!! 点击看题意 思路来自 这位大佬 。 为什么这么好的题解没人评论。 Part 1 前置知识:拉格朗日反演(多项式复合),分式域(引入负整数次项)。 条件&a…...
别只盯着协议!用TC8测试案例深度解读车载网络中的ARP与ICMP:安全与稳定的隐藏关卡
车载以太网底层协议实战:从TC8测试案例看ARP与ICMP的安全设计 当一辆现代汽车以100km/h行驶时,其车载网络每秒需要处理超过5000条网络报文。这些报文中的绝大多数,都由ARP和ICMP这样的基础协议承载。在传统IT领域被视为"简单"的协议…...
快速部署MinerU镜像:开箱即用的PDF提取方案,告别繁琐配置
快速部署MinerU镜像:开箱即用的PDF提取方案,告别繁琐配置 1. 引言:为什么你需要一个“开箱即用”的PDF提取工具? 如果你曾经尝试过从一份复杂的PDF文档里提取文字、表格和公式,你大概率经历过这样的痛苦:…...
腾讯混元翻译模型HY-MT1.5-1.8B:免费开源,企业级翻译解决方案
腾讯混元翻译模型HY-MT1.5-1.8B:免费开源,企业级翻译解决方案 1. 引言 1.1 为什么选择HY-MT1.5-1.8B 在全球化的商业环境中,语言障碍成为企业拓展国际市场的首要挑战。腾讯混元团队推出的HY-MT1.5-1.8B翻译模型,以其18亿参数的…...
半导体器件入门:金半接触的5个关键概念解析(附手稿能带图)
半导体器件入门:金半接触的5个关键概念解析(附手稿能带图) 第一次翻开半导体物理教材时,金半接触那一章总是让人既兴奋又困惑。那些弯曲的能带图、费米能级的移动、神秘的势垒高度,就像一道通往微电子世界的大门。本文…...
软文SEO的常见指标有哪些_如何撰写有吸引力的软文标题
<h2>软文SEO的常见指标有哪些</h2> <p>在当今的数字营销领域,软文(Soft Article)已经成为推动网站流量和品牌知名度的重要工具。要让软文真正发挥作用,我们必须了解软文SEO的常见指标,这些指标可以帮…...
Magisk完整实践指南:从Root权限获取到系统级定制
Magisk完整实践指南:从Root权限获取到系统级定制 【免费下载链接】Magisk The Magic Mask for Android 项目地址: https://gitcode.com/GitHub_Trending/ma/Magisk Magisk作为Android系统Root权限管理的主流解决方案,提供了系统级定制能力而无需修…...
5G网络规划避坑指南:PRACH时频资源配置详解与常见配置错误排查
5G网络规划避坑指南:PRACH时频资源配置详解与常见配置错误排查 在5G网络部署与优化过程中,随机接入信道(PRACH)的配置直接影响终端接入成功率与用户体验。许多网络性能问题,如高接入延迟、频繁接入失败,往往…...
Deepseek 1.5B vs 14B实测:游戏本跑大模型选哪个?吞吐量/显存占用/响应速度全对比
Deepseek 1.5B与14B模型实战评测:游戏本部署大语言模型的黄金分割点 当游戏本遇上大语言模型,性能与显存的博弈便成为开发者最头疼的问题。去年还在为能否跑通7B模型发愁的硬件环境,如今已经能流畅运行14B参数规模的模型——这背后是量化技术…...
cobalt代码覆盖率报告:提升测试质量的关键指标
cobalt代码覆盖率报告:提升测试质量的关键指标 【免费下载链接】cobalt best way to save what you love 项目地址: https://gitcode.com/GitHub_Trending/cob/cobalt 引言:为什么代码覆盖率(Code Coverage)至关重要 在现…...
收藏必备!小白程序员快速入门RAG,轻松提升大模型生成效果与准确性
RAG(检索增强生成)是一种提升大模型生成内容准确性和时效性的技术框架。通过从外部知识库检索信息,再将检索结果与大模型结合,有效解决大模型知识过时和幻觉问题。RAG流程包括知识嵌入存储、相似度检索和增强生成三个核心环节&…...
