Vue.js学习笔记(四)抽奖组件封装——九宫格抽奖

基于VUE2九宫格组件的开发

文章目录

  • 基于VUE2九宫格组件的开发
  • 前言
  • 一、开发步骤
    • 1.数据准备
    • 2.页面布局
    • 3.事件方法
  • 二、最终效果
  • 总结


前言

由于业务需求,需要手动开发九宫格抽奖组件,特此记录学习宫格组件开发。


一、开发步骤

1.数据准备

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

 data() {return {/** dom内使用window对象需要先声明,否则报错 */window,goPointer: require("@/assets/images/goPointer.png"),/** 活动设置 */activeInfo: {/** * 中奖概率,需要根据自己的业务需求定义格式* 由于后台只会填写会中奖的奖项* 所以后面需要自己补齐未中奖的数据 */probabilities: {"一等奖": 10,"二等奖": 10,"三等奖": 10,"四等奖": 10},/** * 奖品信息,用于获取下标* 包含奖项和未中奖,一维数组 */prizeList: [],/** * 奖品信息,用于页面渲染* 包含奖项和未中奖,二维数组 */prizeListCol: []},/** 选中状态样式 */activeStyle: {backgroundColor: '#FDE2E1',borderColor: '#F25561',color: '#F25561'},/** 抽奖动画 */animationInfo: {/** 是否处于抽奖状态 */isTurnOver: false,/** 抽奖次数 */goTimes: 3,/** 中奖结果下标 */winningIndex: null,/** 中奖名字 */winningName: '',/** 初始化速度 */startSpeed: 150,/** 动画实时速度 */speed: 0,/** 定时器实例 */interval: null,/** 最大抽奖时长 */maxAnimationTime: 4500,/** 当前走到的index */activeIndex: null,/** 动画路径数组 */rorateArr: [0, 1, 2, 4, 7, 6, 5, 3],/** 动画第一格 */rotateIndex: 0,/** 开始时间 */startTime: null,/** 结束时间 */endTime: null}}},

created 代码如下:主要处理请求回来的奖项数据

created() {let data = [{name: '一等奖',describe: '一等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg',isSelected: false},{name: '二等奖',describe: '二等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg',isSelected: false},{name: '三等奖',describe: '三等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg',isSelected: false},{name: '四等奖',describe: '四等奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg',isSelected: false},];/** 不足8个数据自动补足 */while (data.length < 8) {for (let i = 0; i < data.length; i++) {data.splice(i * 2 + 1, 0, {name: '未中奖',describe: '未中奖',img: 'https://img01.yzcdn.cn/vant/cat.jpeg'});if (data.length >= 8) {break;}}}/** 把Z字形下标转为O型 */const newData = nineGridOrder(data, 3);this.activeInfo.prizeList.push(...newData);/** 切割成二维数组用于渲染页面 */const TDData = spliceArray(newData, 3);this.activeInfo.prizeListCol.push(...TDData);},

数据处理所用到的方法

/***  将顺序从Z型布局变成圈型布局*  @param arr Array, 待改变顺序的数组*  @param level Number, 所希望生成的多宫格的层级*  @return 改变顺序后的数组* */
export function nineGridOrder(arr, level) {if (Array.isArray(arr) && arr.length == (4 * level - 4)) {// 对数据进行浅拷贝let list = [...arr];// 在当前层级下期望的元素总个数const expectCount = 4 * level - 4;// 取要进行对应插入的尾部let tailArr = list.splice(expectCount - level + 2, expectCount).reverse();// 取要进行翻转处理的尾部let otherTail = list.splice(expectCount - 2 * level + 2, expectCount).reverse();// 进行对应插入for (let i = 0; i < tailArr.length; i++) {list.splice(level + 2 * i, 0, tailArr[i])}// 重新组合后输出return list.concat(otherTail)} else {throw ('层级与数据对应不正确,请检查输入层级后重试')}
}/***  function, 对数组进行分组处理,比如8个元素的数组会被分成3+2+3*  @param arr Array, 待处理的数组*  @param level Number, 所希望生成的多宫格的层级*  @return Array,改变后的数组* */
export function spliceArray(arr, level) {if (Array.isArray(arr) && level >= 3) {let list = [...arr];let head = list.splice(0, level);let tail = list.splice(list.length - level, list.length - 1);let tempArr = departArray(list, 2);tempArr.unshift(head);tempArr.push(tail);return tempArr}
}/** 将数组按两个一组进行分组 */
function departArray(arr, length, store) {let list = [...arr];let temList = store || [];if (list.length >= length) {temList.push(list.splice(0, length))return departArray(list, length, temList);} else {return temList;}
}

2.页面布局

组件用到了vant2,可以根据自己需要改成原生DOM,或者其他组件库的组件

<template><div :class="device"><!-- 内容 --><van-row class="container"><van-col span="24" class="gridBox"><div class="gridMain" :style="`height:${window.innerWidth * 0.9}px;width:${window.innerWidth * 0.9}px;`"><van-row v-for="(item, index) in activeInfo.prizeListCol" :key="index" class="gridRow"><van-col span="8" v-for="(items, indexs) in item" :key="indexs" class="gridCol"><div :style="items.isSelected ? activeStyle : ''"><p>{{ items.name }}</p><!-- <img :src="items.img" /> --></div></van-col></van-row><div class="go"><div @click="go">立即抽奖</div></div></div></van-col></van-row></div>
</template>

样式,使用了less样式预处理器

<style lang="less">
.container {min-height: 100vh;width: 100%;
}.gridBox {float: none;.gridMain {margin: 30px auto;position: relative;}.gridRow {display: flex;justify-content: space-between;width: 100%;height: 33.33%;.gridCol {box-sizing: border-box;padding: 10px;height: 100%;overflow: hidden;display: table;div {display: table-cell;vertical-align: middle;border: 2px solid #F6C494;border-radius: 8px;background-color: #fff;color: #F6C494;img {width: 100%;height: auto;}}}}.gridRow::after {display: none;}.go {position: absolute;width: 33.33%;height: 33.33%;box-sizing: border-box;text-align: center;line-height: 100%;padding: 10px;top: calc(50% - (33.33% / 2));left: calc(50% - (33.33% / 2));display: table;div {background: #F25B52;border: 2px solid #FAE5CC;color: #FFF;display: table-cell;vertical-align: middle;border-radius: 8px;font-size: 18px;font-weight: bold;letter-spacing: 2px;}}
}
</style>

3.事件方法

/** 计算方法 */
computed: {/** 动画运行时长 */rotateTime() {return this.animationInfo.endTime - this.animationInfo.startTime},/** 动画运行速度 */speedIntervalValue() {return this.animationInfo.startSpeed / 10}},/** 事件 */methods: {/** 获取抽奖结果 */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 "未中奖";},/** 点击抽奖 */go() {if (!this.animationInfo.isTurnOver && this.animationInfo.goTimes > 0) {this.animationInfo.isTurnOver = true;/** 抽奖结果 */const result = this.generatePrize();this.animationInfo.winningName = result;/** * 获取奖项下标* 奖项名字可能会重复,所以需要找到奖项的所有下标保存到数组里* 根据下标数组随机生成一个数字来决定选择哪个下标成为最终结果的下标*  */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);this.animationInfo.winningIndex = resultIndexArray[randomResultIndex];this.animationInfo.goTimes--;this.reset();const timeout = setTimeout(() => {this.lottery()clearTimeout(timeout)}, this.animationInfo.speed)}else if (!this.animationInfo.isTurnOver && this.animationInfo.goTimes <= 0) {this.$toast({message: '抱歉,您的抽奖次数用完了',duration: 3000,});}else {this.$toast('请勿重复点击')}},/** 抽奖动画逻辑 */lottery() {/** 清除旧定时器 */clearInterval(this.animationInfo.interval)this.animationInfo.interval = null;if (!this.animationInfo.isTurnOver) { return }/** 变动动画速度,逐渐加快 */this.animationInfo.speed -= this.speedIntervalValue;if (this.animationInfo.speed <= 50) {/** 最快速度 */this.animationInfo.speed = 50};/** 距离动画时间结束不到3秒时,动画逐渐减慢 */if (this.animationInfo.maxAnimationTime - this.rotateTime <= 2000) {/** 这里加两倍,因为再次进入lottery方法,默认会减一倍,所以这里实际上是相当于加一倍*/this.animationInfo.speed += this.speedIntervalValue * 2}if (this.rotateTime > this.animationInfo.maxAnimationTime) {/** 超过时长了 */if (this.animationInfo.winningIndex == this.animationInfo.activeIndex) {/** 动画跑到了中奖奖品所在位置 */this.animationInfo.isTurnOver = false;this.$toast(this.animationInfo.winningName === '未中奖' ? '很遗憾,您未中奖!' : `恭喜您,获得${this.animationInfo.winningName}`)return}}this.rotate();this.animationInfo.interval = setInterval(this.lottery, this.animationInfo.speed)},/** 选中高亮 */rotate() {/** 从第一开始跑 */ if (this.animationInfo.rotateIndex === this.animationInfo.rorateArr.length) {this.animationInfo.rotateIndex = 0;this.activeInfo.prizeList[this.animationInfo.rotateIndex].isSelected = true;}/** 走到哪就点亮哪个方格 */ this.animationInfo.activeIndex = this.animationInfo.rorateArr[this.animationInfo.rotateIndex];this.activeInfo.prizeList.forEach((item, index) => {if (this.animationInfo.activeIndex === index) {this.activeInfo.prizeList[index].isSelected = true;} else {this.activeInfo.prizeList[index].isSelected = false;}})this.animationInfo.endTime = new Date().getTime();/** 记录当前位置 */ this.animationInfo.rotateIndex += 1;},/** 重置 */reset() {this.animationInfo.startTime = new Date().getTime();this.animationInfo.endTime = this.animationInfo.startTime;this.animationInfo.speed = this.animationInfo.startSpeed;this.animationInfo.rotateIndex = 0;}
}

二、最终效果

在这里插入图片描述


总结

以上就是今天要讲的内容,本文仅仅简单介绍了九宫格抽奖组件的基本实现,仅供学习参考。

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

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

相关文章

抽象步骤条(2.0版本)

vue3 router ele-plus 猜猜看为什么使用组件库&#xff01; 他呀的&#xff01;查看密码要自己写&#xff0c;验证信息也要自己写&#xff0c;所以说会用组件库会轻松一点&#xff0c;&#xff0c;&#xff0c; 代码如下 <template><div class"main"&g…

智能驾驶规划控制理论学习06-基于优化的规划方法之数值优化基础

目录 一、优化概念 1、一般优化问题 2、全局最优和局部最优 二、无约束优化 1、无约束优化概述 2、梯度方法 通用框架 线性搜索 回溯搜索 3、梯度下降 基本思想 实现流程 ​4、牛顿法 基本思想 实现流程 5、高斯牛顿法 6、LM法&#xff08;Le…

构建可视化工具选择策略

更多的信息总是意味着更好的结果吗&#xff1f;这完全取决于项目所处的环境。 以烘焙为例。当你做蛋糕时&#xff0c;你的原材料经历了许多化学变化和烹制过程。如果任何一个环节出现问题&#xff0c;蛋糕就做不好。但这并不意味着你需要理解食材在分子级别上发生了什么&#…

YOLO系列中的“data.yaml”详解!

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、data.yaml介绍 YOLO系列中的data.yaml文件包含了YOLO系列模型运行所需要的数据集路径、数据集中的类别数及标签。数据集路径可以用绝对路径也可以…

RISC-V特权架构 - 中断与异常概述

RISC-V特权架构 - 中断与异常概述 1 中断概述2 异常概述3 广义上的异常3.1 同步异常3.2 异步异常3.3 常见同步异常和异步异常 本文属于《 RISC-V指令集基础系列教程》之一&#xff0c;欢迎查看其它文章。 1 中断概述 中断&#xff08;Interrupt&#xff09;机制&#xff0c;即…

mapbox加载全球3D建筑

本案例使用Mapbox GL JavaScript库进行加载全球3D建筑。 文章目录 1. 引入 CDN 链接2. 创建地图3. 监听地图加载完成事件3.1. 获取地图的样式中的图层3.2. 查找图层3.3. 添加三维建筑图层 4. 演示效果5. 代码实现 1. 引入 CDN 链接 <!-- 1.引入CDN链接 --> <script sr…

bert 相似度任务训练简单版本,faiss 寻找相似 topk

目录 任务 代码 train.py predit.py faiss 最相似的 topk 数 任务 使用 bert-base-chinese 训练相似度任务&#xff0c;参考&#xff1a;微调BERT模型实现相似性判断 - 知乎 参考他上面代码&#xff0c;他使用的是 BertForNextSentencePrediction 模型&#xff0c;Bert…

基于springboot+vue实现民宿管理系统项目【项目源码+论文说明】

基于springbootvue民宿管理系统演示 摘要 伴随着我国旅游业的快速发展&#xff0c;民宿已成为最受欢迎的住宿方式之一。民宿借助互联网和移动设备的发展&#xff0c;展现出强大的生命力和市场潜力。民宿主要通过各种平台如携程、去哪儿、淘宝等在网络上销售线下住宿服务&#…

伪创新的迷惑手法-UMLChina建模知识竞赛第5赛季第6轮

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 参考潘加宇在《软件方法》和UMLChina公众号文章中发表的内容作答。在本文下留言回答。 只要最先答对前3题&#xff0c;即可获得本轮优胜。 如果有第4题&#xff0c;第4题为附加题&am…

Git入门学习笔记

Git 是一个非常强大的分布式版本控制工具&#xff01; 在下载好Git之后&#xff0c;鼠标右击就可以显示 Git Bash 和 Git GUI&#xff0c;Git Bash 就像是在电脑上安装了一个小型的 Linux 系统&#xff01; 1. 打开 Git Bash 2. 设置用户信息&#xff08;这是非常重要的&…

JS逆向进阶篇【去哪儿旅行登录】【下篇-逆向Bella参数JS加密逻辑Python生成】

目录&#xff1a; 每篇前言&#xff1a;引子——本篇目的1、 代码混淆和还原&#xff08;1&#xff09;单独替换&#xff1a;&#xff08;2&#xff09;整个js文件替换&#xff1a; 2、算法入口分析3、 深入分析&#xff08;0&#xff09;整体分析&#xff1a;&#xff08;1&am…

在K8S集群中部署SkyWalking

1. 环境准备 K8S 集群kubectlhelm 2. 为什么要部署SkyWalking&#xff1f; 我也不道啊&#xff0c;老板说要咱就得上啊。咦&#xff0c;好像可以看到服务的各项指标&#xff0c;像SLA&#xff0c;Apdex这些&#xff0c;主要是能够进行请求的链路追踪&#xff0c;bug排查的利…