vue实现大转盘抽奖

用vue实现一个简单的大转盘抽奖案例

大转盘

一 转盘布局

<div class="lucky-wheel-content"><div class="lucky-wheel-prize" :style="wheelStyle" :class="isStart ? 'animated-icon' : ''"@transitionend="onWheelTransitionEnd"><div class="lucky-wheel-prize-item" v-for="(item, index) in prize" :key="item.id":style="{ transform: 'rotate(' + (index * 36) + 'deg)' }"><span>{{ item.reward }}</span><img :src="item.img" alt=""></div></div><div class="lucky-wheel-btn" @click="spinWheel">RODAR</div><img class="lucky-wheel-poiner" src="/img/activity/zphd_zz_s1.avif" /></div>

1.1 :style=“{ transform: ‘rotate(’ + (index * 36) + ‘deg)’ }”

  1. v-for=“(item, index) in prize”:这表示你正在循环渲染 prize 数组中的每个项目,每个项目都有一个
    item 和其在数组中的 index。这个 index 就是每个奖品项的位置。
  2. index * 36:每个项目的旋转角度是基于其索引计算的。这里每个项目的旋转角度是 36 度(360 ÷ 10 = 36),因为假设转盘有 10 项。通过将 index 乘以 36,每个项目将被均匀地分布在转盘上。
  3. :style=“{ transform: ‘rotate(’ + (index * 36) + ‘deg)’ }”:这段代码为每个
    lucky-wheel-prize-item 动态添加一个内联的 style 属性,指定它的 transform CSS 样式。这个
    transform 样式使用 rotate() 函数来旋转每个奖品项。
  4. rotate(index * 36):基于 index 计算出每个项目的旋转角度。比如:
  • 对于第一个项目(index = 0),旋转角度是 0deg。
  • 对于第二个项目(index = 1),旋转角度是 36deg。
  • 对于第三个项目(index = 2),旋转角度是 72deg,以此类推。
    效果:通过这种方式,每个 lucky-wheel-prize-item 将会根据它在转盘上的位置进行旋转,使它们均匀分布在 360 度的转盘上。这样,整个转盘就呈现出一个环形布局,每个项按顺序排列。

在这里插入图片描述

计算转盘旋转的样式

通过计算属性

const wheelStyle = computed(() => {return {transform: `rotate(${rotationAngle.value}deg)`,}
});
  • rotationAngle 是某个响应式变量(可能是通过其他逻辑计算出来的旋转角度),它的值决定了转盘旋转的角度。
  • 当 rotationAngle.value 发生变化时,computed 属性会自动重新计算并返回新的样式对象,其中
    rotate(${rotationAngle.value}deg) 的角度会根据最新的 rotationAngle.value 动态更新。
  • 然后,这个 wheelStyle 对象可以应用到某个 DOM 元素上,通常是一个转盘的 style 属性,以便旋转转盘。
<div :style="wheelStyle"><!-- 转盘内容 -->
</div>

二 转盘逻辑

2.1 这里最重要的是转盘总的旋转角度的设置

  spins.value += 5;  // 开始的旋转圈数// 后端返回中奖项的逻辑  随机数winningIndex.value = Math.floor(Math.random() * totalItems.value);console.log("中奖项:" + winningIndex.value);const anglePerItem = 360 / totalItems.value;let randomAngle = 360 - (winningIndex.value * anglePerItem); // 计算旋转到中奖的那一项let totalAngle = spins.value * 360 + randomAngle; // 总的旋转角度console.log("总的旋转角度:" + totalAngle);// 设置旋转角度rotationAngle.value = totalAngle;
  • let randomAngle = 360 - (winningIndex.value * anglePerItem);
    randomAngle 是根据中奖项索引计算出的角度。winningIndex.value 乘以 anglePerItem 得到当前中奖项相对于起始位置的角度,360 - … 计算出从当前起始位置到中奖项的逆时针旋转角度。

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

在这里插入图片描述

2.2 在请求后端获取数据时,保持转动效果

  • :class=“isStart ? ‘animated-icon’ : ‘’”
    主要是通过加上这个类名来保持这个效果
  spins.value += 5;isStart.value = trueapi.getRandom().then(res => {console.log(res);isStart.value = falsewinningIndex.value = res.data// 每个奖品的角度const anglePerItem = 360 / totalItems.value;// 计算中奖项的角度let randomAngle = 360 - (winningIndex.value * anglePerItem);let totalAngle = spins.value * 360 + randomAngle; // 总的旋转角度// 设置旋转角度rotationAngle.value = totalAngle;}).finally(() => {console.log('中奖项是:' + prize[winningIndex.value].reward);isSpinning.value = falseisStart.value = false})

api.getRandom()这个是我本地java写的一个接口,模拟返回一个中奖的索引,同时该接口延迟5s返回数据

   @GetMapping("/random")public Result<Integer> getRandom(){try {// 延迟5秒Thread.sleep(5000);} catch (InterruptedException e) {// 处理异常e.printStackTrace();}Random random = new Random();Integer integer = random.nextInt(10); // 生成0到10之间的随机整数return Result.success(integer); // 返回成功结果}

大转盘1

三 完整代码

 <div class="lucky-wheel-content"><div class="lucky-wheel-prize" :style="wheelStyle" :class="isStart ? 'animated-icon' : ''"@transitionend="onWheelTransitionEnd"><div class="lucky-wheel-prize-item" v-for="(item, index) in prize" :key="item.id":style="{ transform: 'rotate(' + (index * 36) + 'deg)' }"><span>{{ item.reward }}</span><img :src="item.img" alt=""></div></div><div class="lucky-wheel-btn" @click="spinWheel">RODAR</div><img class="lucky-wheel-poiner" src="/img/activity/zphd_zz_s1.avif" /></div>
const prize = [{id: 1,reward: '0,05',img: '/img/activity/img_zphdjp_s1.png'}, {id: 2,reward: '1,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 3,reward: '2,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 4,reward: '3,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 5,reward: '4,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 6,reward: '5,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 7,reward: '15,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 8,reward: '25,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 9,reward: '35,00',img: '/img/activity/img_zphdjp_s1.png'}, {id: 10,reward: '75,00',img: '/img/activity/img_zphdjp_s1.png'}
]
const totalItems = ref(prize.length); // 总共有多少个项
const winningIndex = ref(0); // 假设中奖项的索引(从0开始)
const rotationAngle = ref(0); // 当前旋转角度
const isSpinning = ref(false)
const spins = ref(0) //转盘转5圈
const winner = ref(null); // 中奖项
const number = ref(0)  //记录抽奖次数
const isFirst = ref(0)
const isStart = ref(false)
// 计算转盘旋转的样式
const wheelStyle = computed(() => {return {transform: `rotate(${rotationAngle.value}deg)`,}});// 执行旋转转盘的操作
const spinWheel = () => {if (isSpinning.value) {return}number.value++;isStart.value = trueconsole.log("当前抽奖次数:" + number.value);isSpinning.value = true; // 开始旋转winner.value = null; // 重置中奖项winningIndex.value = 0; // 重置中奖索引rotationAngle.value = 0; // 重置旋转角度spins.value += 5;// api.getRandom().then(res => {//   console.log(res);//     isStart.value = false//   winningIndex.value = res.data//   // 每个奖品的角度//   const anglePerItem = 360 / totalItems.value;//   // 计算中奖项的角度//   let randomAngle = 360 - (winningIndex.value * anglePerItem);//   let totalAngle = spins.value * 360 + randomAngle; // 总的旋转角度//   // 设置旋转角度//   rotationAngle.value = totalAngle;// }).finally(()=>{//   // console.log('中奖项是:'+prize[winningIndex.value].reward );//   isSpinning.value=false// })// 后端返回中奖项的逻辑  随机数winningIndex.value = Math.floor(Math.random() * totalItems.value);// 假设每次转盘转5圈// spins.value += 5;setTimeout(()=>{isStart.value = falseisSpinning.value=falseconsole.log('中奖项是:'+prize[winningIndex.value].reward );},2000)// 每个奖品的角度const anglePerItem = 360 / totalItems.value;// 计算中奖项的角度let randomAngle = 360 - (winningIndex.value * anglePerItem);let totalAngle = spins.value * 360 + randomAngle; // 总的旋转角度// 设置旋转角度rotationAngle.value = totalAngle;
};// 监听转盘动画结束事件
const onWheelTransitionEnd = () => {isSpinning.value = false; // 旋转结束// rotationAngle.value=0winner.value = winningIndex.value; // 显示中奖项// console.log(winner.value, '123');// console.log(rotationAngle.value, '旋转角度');console.log('中奖项是:'+prize[winner.value].reward );};
.lucky-wheel {.lucky-wheel-content {width: 15rem;height: 15rem;background-image: url('/img/activity/zphd_bj_s1.avif');background-size: 100% 100%;margin: .4rem auto .4rem auto;position: relative;transition: transform 5s ease-in-out;.lucky-wheel-prize {position: absolute;top: 0;right: 0;bottom: 0;left: 0;transition: transform 4s ease-out;/* 控制旋转动画 */.lucky-wheel-prize-item {position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 10;width: 2rem;margin: auto;height: 100%;color: #ffff;font-size: .22rem;text-align: center;display: flex;align-items: center;flex-direction: column;&>img {width: 2rem;height: 2rem;}&>span {display: -webkit-box;overflow: hidden;text-overflow: ellipsis;vertical-align: middle;-webkit-line-clamp: 2;-webkit-box-orient: vertical;font-size: .6rem;word-break: break-all;height: 2.8rem;line-height: 2.8rem;}}}@keyframes spin {0% {transform: rotate(0deg);/* 开始时从0度 */}100% {transform: rotate(360deg);/* 结束时旋转一圈 */}}/* 应用动画 */.animated-icon {display: inline-block;animation: spin 1s linear infinite;/* 1秒旋转一圈,永远循环 */}

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

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

相关文章

Docker 核心组件

一、前言 Docker 已成为现代 DevOps 和微服务架构中的核心工具。为了更深入地理解它的工作机制&#xff0c;本文将系统介绍 Docker 的核心组件&#xff0c;配合结构图直观展示架构&#xff0c;同时拓展高级用法&#xff0c;帮助读者全面掌握容器化技术的内核。 二、Docker 核心…

ModuleNotFoundError: No module named ‘pandas‘

在使用Python绘制散点图表的时候&#xff0c;运行程序报错&#xff0c;如图&#xff1a; 报错显示Python 环境中可能没有安装 pandas 库&#xff0c;执行pip list命令查看&#xff0c;果然没有安装pandas 库&#xff0c;如图&#xff1a; 执行命令&#xff1a;python -m pip in…

(51单片机)矩阵按键密码锁表白(C语言代码编撰)(矩阵按键教程)(LCD1602浅教程)

目录 源代码 main.c MatrixKey.c MatrixKey.h LCD1602.c LCD1602.h Delay.c Delay.h 运行效果图&#xff1a; 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 第四步&#xff1a; 代码解析与教程&#xff1a; 延时函数Delay LCD1602 MatrixKey模块 源代…

检测手机插入USB后,自动启动scrcpy的程序

博主写了一个小工具scrcpyAuto&#xff0c;检测手机插入电脑USB后&#xff0c;自动启动scrcpy。 这样只要程序运行&#xff0c;手机接入主机就会有scrcpy大屏出现&#xff0c;方便了很多。 1、程序会最小化到系统托盘中。 2、博主没有设计得太复杂&#xff0c;所以程序开机启动…

使用Scade实现神经网络算法

在ERTS2022中&#xff0c;ANSYS 发表了使用Scade实现神经网络AI算法的相关工作。论文题目为《Programming Neural Networks Inference in a Safety-Critical Simulation-based Framework》 背景与挑战 神经网络在安全关键系统中的应用&#xff1a;随着嵌入式系统中自主性的引入…

Next.js + SQLite 项目 Docker 生产环境部署方案

以下是完整的 Next.js SQLite 项目 Docker 生产环境部署方案&#xff1a; 1. 项目结构准备 your-project/ ├── prisma/ │ ├── schema.prisma │ └── migrations/ ├── app/ ├── lib/ ├── Dockerfile ├── docker-compose.yml ├── .dockerignore └…

MCU软件开发使用指针有哪些坑?

目录 1、空指针访问 2、野指针&#xff08;未初始化的指针&#xff09; 3、指针越界 4、内存泄漏 5、悬空指针 6、指针类型不匹配 7、多任务环境中的指针访问 8、对齐问题 在MCU软件开发中&#xff0c;使用指针虽然可以提高程序的灵活性和性能&#xff0c;但也存在许多…

【SPSS/EXCEl】主成分分析构建__综合评价指数

学习过程中实验操作的记录 1.数据准备和标准化&#xff1a; (1)区分正负相关性:判断每个因子是正向指标还是负向指标,计算每个的最大值和最小值 (2) 标准化: Min-Max标准化 Min-Max标准化&#xff08;最大最小值法&#xff09;&#xff1a; 将数据映射到指定的区间&#xff…

selenium安装,以及浏览器驱动下载详细步骤

1.下载谷歌浏览器Chromedriver 查看谷歌浏览器版本 2.去官网下载Chromedriver 114之前的版本链接chromedriver.storage.googleapis.com/index.html 选择和浏览器版本较接近的点击进行下载 125之后的版本链接Chrome for Testing availability (googlechromelabs.github.io)&a…

LabVIEW 油井动液面在线监测系统​

项目背景 传统油井动液面测量依赖人工现场操作&#xff0c;面临成本高、效率低、安全风险大等问题。尤其在偏远地区或复杂工况下&#xff0c;测量准确性与时效性难以保障。本系统通过LabVIEW虚拟仪器技术实现硬件与软件深度融合&#xff0c;为油田智能化转型提供实时连续监测解…

C++标准库 —— round 函数用法详解

round 是 C/C 标准库中的一个数学函数&#xff0c;用于对浮点数进行四舍五入取整。以下是它的详细用法说明&#xff1a; 目录 1. 基本语法 2. 功能描述 3. 使用示例 示例1&#xff1a;基本用法 示例2&#xff1a;保留小数位 4. 相关函数对比 5. 注意事项 6. 实际应用场景…

嵌入式C语言11(宏/程序的编译过程)

宏 ⦁ 基本概念 C语言中可以利用宏定义实现文本的快速替换&#xff0c;注意&#xff1a;宏定义是单纯的文本替换&#xff0c;不检查语法是否合法。 C语言标准中提供了很多的预处理指令&#xff0c;比如#include、#pragma…以#开头的都属于预处理指令。 预处理指令指的是在…

【湖南大学】2025我们该如何看待DeepSeek

大家好&#xff0c;我是樱木。 DeepSeek 官方网站&#xff1a;https://www.deepseek.com/ 一、DeepSeek 到底是什么&#xff1f; TA 到底厉害在哪里&#xff1f; 故事从 ChatGPT 说起 去年我们看到 Open AI 发布ChatGPT 后&#xff0c;全球的注意力到了 AI 身上。 我们来拆…

【区块链安全 | 第三十三篇】备忘单

文章目录 备忘单操作符优先级备忘单ABI 编码和解码函数bytes 和 string 的成员Address 的成员区块与交易属性校验和断言数学和加密函数合约相关类型信息函数可见性说明符修饰符备忘单 操作符优先级备忘单 以下是操作符的优先级顺序,按评估顺序列出: 优先级描述操作符1后缀递…

Python----计算机视觉处理(Opencv:道路检测之车道线显示)

完整版&#xff1a;Python----计算机视觉处理&#xff08;Opencv:道路检测完整版&#xff1a;透视变换&#xff0c;提取车道线&#xff0c;车道线拟合&#xff0c;车道线显示&#xff09; 一、透视变换 将透视变换之后的图像再继续透视变换为原图像 可参考Python----计算机视…

26届Java暑期实习面经,腾讯视频一面

短链接的生成原理 如何解决短链接生成的哈希冲突问题 如何加快从短链接到原链接的重定向过程 TCP 和 UDP 协议 如何理解 TCP 是面向连接的 为什么 TCP 的握手是 3 次 IO 模式 是否有真正写过一个底层的 Socket 通信 MySQL 的事务隔离级别 MVCC 机制 什么叫服务的并行 为什么能基…

Windows注册鼠标钩子,获取用户选中的文本

注册鼠标钩子 // 注册鼠标钩子 HHOOK hMouseHook; hMouseHook SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), 0);// 取消鼠标钩子 UnhookWindowsHookEx(hMouseHook); hMouseHook nullptr; 上述代码中MouseProc方法用于处理系统的鼠标消息 处理鼠标消息…

flink cdc的source数据流如何配置事件时间,如何设置时间语义,分配时间戳并生成水位线

在 Flink CDC 中为 Source 数据流配置事件时间需要结合时间语义设置、时间戳分配和水位线生成三个核心步骤。以下是具体配置方法及注意事项&#xff1a; 1. 设置时间语义 Flink 默认使用处理时间&#xff08;Processing Time&#xff09;&#xff0c;需显式指定事件时间语义&a…

C++ 指针类型转换全面解析与最佳实践

文章目录 C 指针类型转换全面解析与最佳实践1. 隐式转换基类和派生类指针 2. 显式转换(1) static_cast(2) dynamic_cast(3) reinterpret_cast(4) const_cast 3. C 风格转换4. 常见问题与注意事项5. 总结最佳实践 C 指针类型转换全面解析与最佳实践 在 C 中&#xff0c;指针类型…

批量将 txt/html/json/xml/csv 等文本拆分成多个文件

我们的文本文件太大的时候&#xff0c;我们通常需要对文本文件进行拆分&#xff0c;比如按多少行一个文件将一个大的文本文件拆分成多个小的文本文件。这样我们在打开或者传输的时候都比较方便。今天就给大家介绍一种同时对多个文本文件进行批量拆分的方法&#xff0c;可以快速…