Vue.js学习笔记(五)抽奖组件封装——转盘抽奖

基于VUE2转盘组件的开发

文章目录

  • 基于VUE2转盘组件的开发
  • 前言
  • 一、开发步骤
    • 1.组件布局
    • 2.布局样式
    • 3.数据准备
  • 二、最后效果
  • 总结


前言

因为之前的转盘功能是图片做的,每次活动更新都要重做UI和前端,为了解决这一问题进行动态配置转盘组件开发,可以减少一些UI和前端的工作量。


一、开发步骤

1.组件布局

 <van-row class="container"><!-- turntableBox 为整个转盘容器,为正方形,大小由里面元素决定 --><van-col span="24" class="turntableBox"><!-- turntableMain 为转盘底座,比里面的内容大,显示为效果图灰色外圈,但不是空心圆 --><div class="turntableMain" :style="`height:${window.innerWidth * 0.8}px;width:${window.innerWidth * 0.8}px;`"><!-- turntable 为转动区域,作用是为了不让外圈一起转动 --><div ref="turntable" class="turntable":style="`height:${window.innerWidth * 0.8}px;width:${window.innerWidth * 0.8}px;`"><!-- Canvas 转盘饼图背景,具体划分多少块由奖项决定 --><Canvas /><!-- prizeBox 奖项,高为饼图的半径,宽为饼图半径里面有多少块就多少分之一 --><div class="prizeBox"><div class="prizeItem" :style="`width:${perPrize.width}px;height:${perPrize.height}px;transform:translateX(-50%) rotate(-${(perPrize.degree * (index + 1)) - (perPrize.degree / 2)}deg);left:calc(50%)`"v-for="(item, index) in activeInfo.prizeList" :key="index"><p class="title">{{ item.name }}</p><p class="describe">{{ item.describe }}</p><img :src="item.img" style="width: 38%;" /></div></div></div><!-- 启动按钮 --><van-image class="go" fit="cover" width="42px" :src="goPointer" @click="go" /></div></van-col><!-- 结果展示列表 --><van-col span="24"><div id="result"></div></van-col></van-row>

2.布局样式

.turntableBox {margin-top: 10%;.turntableMain {margin: 0 auto;position: relative;border: 10px solid #E5E5E5;border-radius: 100%;}.turntable {transition: all 4s;margin: 0 auto;}.go {position: absolute;top: calc(50% - 31px);left: calc(50% - 21px);}.prizeBox {position: absolute;width: 80%;top: 0;left: calc(50% - 40%);.prizeItem {text-align: center;position: absolute;top: 0;overflow: hidden;text-align: center;transform-origin: center bottom;transform: translateX(-50%);color: #2c3e50;p {margin: 0;padding: 0;}.title {font-size: 18px;margin-top: 12px;}.describe {font-size: 14px;line-height: 28px;white-space: break-spaces;}img {margin-top: 6px;}}}
}

3.数据准备

data 代码如下:包含页面功能所需要的变量

  data() {return {window,/** 活动设置 */activeInfo: {/** 中奖概率 */probabilities: {"一等奖": 10,"二等奖": 10,"三等奖": 10,"四等奖": 10,},/** 奖品信息 */prizeList: [{name: '一等奖',describe: '一等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg'},{name: '未中奖',describe: '未中奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg'},{name: '二等奖',describe: '二等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg'},{name: '未中奖',describe: '未中奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg'},{name: '三等奖',describe: '三等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg'},{name: '四等奖',describe: '四等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg'},]},/** 是否正在执行动画 */isGo: false,/** 执行动画的对象 */oTurntable: '',/** 即将旋转的度数 */randomDeg: 0,/** 上一次旋转的度数 */lastDeg: 0,/** 抽奖次数 */goTimes: 3,/** 奖品图片 */perPrize: {degree: null,width: null,height: null}}} 

created 代码如下:主要处理角度、宽、高

  created() {const params = getAllParams();if (params) {this.params = params;};/** 奖品 */const angle = (360 / this.activeInfo.prizeList.length) / 2; // 对角角度const ratio = Number(Math.sin(angle * (Math.PI * 2 / 360)).toFixed(2)); // 与半径的比率this.perPrize = {degree: (360 / this.activeInfo.prizeList.length),width: Math.floor((window.innerWidth * ratio)) / 2,/** 高度是直径的一半 */height: window.innerWidth * 0.8 / 2}},

mounted 代码如下:获取转盘区域DOM元素,方便后面操作

  mounted() {this.oTurntable = this.$refs.turntable;},

methods 代码如下:主要操作方法

 /** 点击抽奖 */go() {/** 正在抽奖,未结束继续点击无效 */if (!this.isGo && this.goTimes > 0) {/** 获取中奖结果,再根据结果去转动转盘 */const result = this.generatePrize();/** * 获取奖项下标* 奖项名字可能会重复,所以需要找到奖项的所有下标保存到数组里* 根据下标数组随机生成一个数字来决定选择哪个下标成为最终结果的下标*  */const resultIndexArray = this.activeInfo.prizeList.reduce((acc, item, index) => {if (item.name === result) {acc.push(index);}return acc;}, []);const randomResultIndex = Math.floor(Math.random() * resultIndexArray.length);const index = resultIndexArray[randomResultIndex];/** 奖项总和数量 */const length = this.activeInfo.prizeList.length;/** 调用旋转方法 */this.ratating((360 / length * index) + (360 / length / 2), result);}else if (!this.isGo && this.goTimes <= 0) {this.$toast({message: '抱歉,您的抽奖次数用完了',duration: 3000,});}else {this.$toast('请勿重复点击')return}},/** 获取抽奖结果 */generatePrize() {/** 生成一个 0 到 99 之间的随机数 */const randomNum = Math.floor(Math.random() * 100);let cumulativeProbability = 0;/** 如果概率落在奖项范围内 */for (const prize in this.activeInfo.probabilities) {cumulativeProbability += this.activeInfo.probabilities[prize];if (randomNum < cumulativeProbability) {/** 返回中奖内容 */return prize;}}// 默认返回未中奖return "未中奖";},/** 该方法能产生[n,m]之间随机数,决定转盘转多少圈 */getRandom(n, m) {let result = Math.floor(Math.floor(Math.random() * (m - n + 1) + n))return result;},/** 旋转 */ratating(deg, text) {this.goTimes--;this.isGo = true;/** 旋转圈数 */let turnNumber = this.getRandom(3, 6);/** 记录这次要旋转的度数(传来的度数+圈数) */this.randomDeg = deg + 360 * turnNumber;/*上次指针离初始状态的度数 + 上次的度数 + 这次要旋转的度数(这样的目的是为了每次旋转都从原点开始,保证数据准确)*/let realDeg = (360 - this.lastDeg % 360) + this.lastDeg + this.randomDeg;/** 为对象添加执行动画 */this.oTurntable.style.transform = `rotate(${realDeg}deg)`;setTimeout(() => {this.isGo = false;var list = document.getElementById('result');list.innerHTML += /未中奖/.test(text) ? `<p>很遗憾,您${text}!</p>` : `<p>恭喜您,获得${text}!</p>`;/** 把这次度数存储起来,方便下一次获取 */this.lastDeg = realDeg;}, 4000);}

canvas 组件代码如下:主要使用canvas标签根据奖项长度进行角度划分绘画,


<template><canvas class="canvas" id="canvasImg" :style="`width:${perimeter}px;height: ${perimeter}px;`">您的浏览器不支持canvas!</canvas>
</template><script>export default {name: 'Canvas',components: {},data() {return {/** 直径 */perimeter: 320,}},created() {},mounted() {this.perimeter = window.innerWidth * 0.8;this.drawPie();},methods: {/** 画饼图 */drawPie() {const PI = Math.PI;/** 获取画布并获取2d上下文对象 */const canvas = document.getElementById('canvasImg');const ctx = canvas.getContext('2d');/** 假设周长为500 */const perimeter = this.perimeter;/** 半径 */const radius = perimeter * 0.5;/** 总奖品数,需要根据实际数据长度从父组件传入 */const prizeTotal = 6;/** 每个扇形的角度=360度 / 总奖品数 */const degree = 360 / prizeTotal;/** 画布宽高 */canvas.width = perimeter;canvas.height = perimeter;/** 根据奖品数把圆形分成等份的扇形 */for (let i = 0; i < prizeTotal; i++) {/** 奇偶颜色 */const color = i % 2 === 0 ? "#F8D383" : "#F8E2BC";/** 开始一条新路径 */ctx.beginPath();/** 设置路径起点 */ctx.moveTo(radius, radius);/** 填充颜色 */ ctx.fillStyle = color;/** 绘制扇形 (圆心坐标,圆心坐标,半径,扇形起始角度,扇形终止角度) */ctx.arc(radius, radius, radius, (270 - degree  + (degree * i)) * PI / 180, (270 - degree  + degree + (degree * i)) * PI / 180);/** 自动绘制一条当前点到起点的直线,形成一个封闭图形,省却使用一次moveTo方法。 */ctx.closePath();/** 闭合路径 */ctx.fill();}}},
}
</script><style lang="less"></style>

二、最后效果

在这里插入图片描述


总结

本文仅仅简单记录了转盘组件的基本实现,仅供学习参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/375826.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何更好地理解递归算法?Python实例详解

递归确实是一种较为抽象的数学逻辑&#xff0c;可以简单的理解为程序调用自身的算法。 维基百科对递归的解释是&#xff1a; 递归&#xff08;英语&#xff1a;Recursion&#xff09;&#xff0c;又译为递回&#xff0c;在数学与计算机科学中&#xff0c;是指在函数的定义中使…

pbootCMS 数据库sqlite转mysql数据库

前言 pbootCMS默认使用 sqlite数据库 &#xff0c;那么什么是sqlite数据库呢&#xff1f; SQLite&#xff0c;是一款轻型的数据库&#xff0c;是遵守ACID的关系型数据库管理系统&#xff0c;它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌…

【大模型LLM面试合集】大语言模型架构_MoE论文

1.MoE论文 参考文章&#xff1a; Mixture of Experts-IntroductionUnderstanding the Mixture-of-Experts Model in Deep Learning 论文相关&#xff1a; 论文名称&#xff1a;Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer论文地址&a…

Kafka(三)Producer第二篇

一&#xff0c;生产者架构 生产者客户端由两个线程协调运行&#xff0c;分别为主线程和Sender线程&#xff08;发送线程&#xff09;。 主线程&#xff1a;KafkaProducer创建消息&#xff0c;通过拦截器、序列化器和分区器之后缓存到消息收集器RecordAccumulator中&#xff1b;…

jmeter-beanshell学习6-beanshell生成测试报告

前面写了各种准备工作&#xff0c;内容组合用起来&#xff0c;应该能做自动化了&#xff0c;最后一步&#xff0c;生成一个报告&#xff0c;报告格式还是csv 报告生成的路径和文件&#xff0c;在用户参数写好&#xff0c;防止以后改路径或者名字&#xff0c;要去代码里面改。以…

批量提取PDF指定区域内容到 Excel , 根据PDF文件第一行文字来自动重命名v1.3-附思路和代码实现

本次文章更新内容&#xff0c;图片以及扫描的PDF也可以支持批量提取指定区域内容了&#xff0c;主要是通过截图指定区域&#xff0c;然后使用OCR来识别该区域的文字来实现的&#xff0c;所以精度可能会有点不够&#xff0c;但是如果是数字的话&#xff0c;问题不大&#xff1b;…

Java高频面试基础知识点整理9

干货分享&#xff0c;感谢您的阅读&#xff01;背景​​​​​​高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09; 最全文章见&#xff1a;Java高频面试基础知识点整理 &#xff08;一&#xff09;Java基础高频知识考点 针对人员&#xff1a; 1.全部人员都…

农牧行业CRM洞察:打造营、销、服一体化数字营销平台

01、行业应用背景 保持企业活力&#xff0c;支撑业务单元协调发展&#xff0c;稳定核心产品竞争力&#xff0c;将成为农牧行业企业数字化、数智化建设的指导方向。 积极发挥数据在生产、流通、消费各个环节的决策支撑&#xff0c;为农牧企业特别是多业态集团型企业&#xff0…

Cisco 命令速查表(非常详细)零基础入门到精通,收藏这一篇就够了

Cisco IOS&#xff08;Internetwork Operating System&#xff09;是 Cisco 系统公司开发的专有操作系统&#xff0c;用于其路由器和交换机。它提供了一个稳健的、可扩展的、以命令行接口&#xff08;CLI&#xff09;为基础的网络操作环境。通过掌握 Cisco IOS 命令&#xff0c…

conda install问题记录

最近想用代码处理sar数据&#xff0c;解放双手。 看重了isce这个处理平台&#xff0c;在安装包的时候遇到了一些问题。 这一步持续了非常久&#xff0c;然后我就果断ctrlc了 后面再次进行尝试&#xff0c;出现一大串报错&#xff0c;不知道是不是依赖项的问题 后面看到说mam…

通用详情页的打造

背景介绍 大家都知道&#xff0c;详情页承载了站内的核心流量。它的量级到底有多大呢&#xff1f; 我们来看一下&#xff0c;日均播放次数数亿次&#xff0c;这么大的流量&#xff0c;其重要程度可想而知。 在这样一个页面&#xff0c;每一个功能都是大量业务的汇总点。 作为…

Django 删除单行数据

1&#xff0c;添加模型 from django.db import modelsclass Post(models.Model):title models.CharField(max_length200)content models.TextField()pub_date models.DateTimeField(date published)class Book(models.Model):title models.CharField(max_length100)author…

苹果电脑压缩软件哪个好用一些? mac电脑用什么压缩软件 mac电脑压缩文件怎么设置密码

压缩软件是Mac电脑必不可少的工具&#xff0c;虽然Mac系统自带了一款“归档实用工具”&#xff0c;但是其功能实在匮乏&#xff0c;若你需要加密压缩文件或者把文件压缩成指定格式&#xff0c;那么该工具无法满足你的需求。Mac用户应该怎么选择压缩软件呢&#xff1f;本文就来告…

自动驾驶算法———车道检测(一)

“ 在本章中&#xff0c;我将指导您构建一个简单但有效的车道检测管道&#xff0c;并将其应用于Carla 模拟器中捕获的图像。管道将图像作为输入&#xff0c;并产生车道边界的数学模型作为输出。图像由行车记录仪&#xff08;固定在车辆挡风玻璃后面的摄像头&#xff09;捕获。…

一图展示免费开源的分布式版本控制系统​Git

文章目录 前言一、安装Git二、Git配置三、git命令 前言 Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 一、安装Git Windows操作系统…

MFC扩展库BCGControlBar Pro v35.0 - 可视化管理主题等全新升级

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.0已全新发布了&#xff0c;这个版本改进类Visual Studio 2022的视觉主题、增强对多个…

大模型时代的目标检测

https://zhuanlan.zhihu.com/p/663703934https://zhuanlan.zhihu.com/p/6637039341.open set/open word/ood 这个任务是指在实际应用上可以检测任何前景物体&#xff0c;但是有些不需要预测类别&#xff0c;只要检测出框就行。在很多场合也有应用场景&#xff0c;有点像类无关…

ASP.NET MVC Lock锁的测试

思路&#xff1a;我们让后台Thread.Sleep一段时间&#xff0c;来模拟一个耗时操作&#xff0c;而这个时间可以由前台提供。 我们开启两个或以上的页面&#xff0c;第一个耗时5秒(提交5000)&#xff0c;第二个耗时1秒(提交1000)。 期望的测试结果&#xff1a; 不加Lock锁&…

短视频矩阵搭建,用云微客获客更方便

你的同行都爆单了&#xff0c;你还在问什么是矩阵&#xff1f;让我来告诉你。短视频矩阵是短视频获客的一种全新玩法&#xff0c;是以品牌宣传、产品推广为核心的一个高端布局手段&#xff0c;也是非常省钱的一种方式。 1.0时代&#xff0c;一部手机一个账号&#xff1b;2.0时代…

nx上darknet的使用-目标检测-自定义训练与制作预训练模型

目录 1 训练yolov4-tiny 1.1 文件准备 1.1.1 Annotations 1.1.2 JPEGImages 1.1.3 labels 1.1.4 trained_models 1.1.5 classes.name 1.1.6 create_labels_txt.py 1.1.7 custom_training.data 1.1.8 get_labels.py 1.1.9 get_train_val.py 1.1.10 train…