当前位置: 首页 > news >正文

纯CSS+JS制作抽奖大转盘

在大转盘游戏中,使用百分比计算概率是一种直观且常用的方法。这种方法通过为每个奖项分配一定的百分比概率,确保所有奖项的概率总和为 100%,从而实现公平且可控制的抽奖逻辑。

1.HTML代码和样式

<template><!-- 大转盘抽奖 --><div class="bigPages"><div class="bigBox"><div class="out-box" ref="outBox"><div v-for="(item, index) in awardList" :style="{'--i': index,'--color': setColor(index)}"><text>{{item.name}}</text></div></div><div class="inset" @click="awardStart">抽奖</div></div></div>
</template>
<style lang="scss" scoped>@mixin felx-center {display: flex;justify-content: center;align-items: center;}@font-face {font-family: 'diyFont';src: url('../assets/禹卫书法行书简体.ttf');}.bigPages {@include felx-center();height: 100vh;width: 100vw;margin: auto;.bigBox {@include felx-center();position: relative;}.out-box {position: relative;height: 300px;width: 300px;border-radius: 50%;background-color: red;overflow: hidden;// transform: rotate(45deg);div {@include felx-center();position: absolute;height: 50%;width: 150px;overflow: hidden;background-color: var(--color);// transform: rotate(calc(var(--i) * 45deg));transform-origin: right bottom;-webkit-clip-path: polygon(0 0, 37% 0, 100% 100%, 0 60%);clip-path: polygon(0 0, 59% 0, 100% 100%, 0 59%);text {transform: rotate(-45deg) translateY(-20px);}}}.inset {@include felx-center();position: absolute;height: 60px;width: 60px;border-radius: 50%;background-color: #fff;box-shadow: 0 0 3px 2px #fee;font-size: 25px;font-family: 'diyFont';font-weight: bold;cursor: pointer;}.inset::before {content: '';position: absolute;// top: -78px;// right: 20px;// border: 40px solid #fff;// border-left-width: 10px;// border-right-width: 10px;// border-left-color: transparent;// border-right-color: transparent;// border-top-color: transparent;top: -38px;right: 20px;height: 40px;width: 20px;-webkit-clip-path: polygon(50% 0, 0 100%, 100% 100%);clip-path: polygon(50% 0, 0 100%, 100% 100%);background-color: #fff;}}
</style>

2.JS实现逻辑

<script setup>import {ref,onMounted} from "vue"const awardList = ref([{name: '1号奖品',precent: 5}, //5%{name: '2号奖品',precent: 5},{name: '3号奖品',precent: 10},{name: '4号奖品',precent: 10},{name: '5号奖品',precent: 15},{name: '6号奖品',precent: 15},{name: '7号奖品',precent: 15},{name: '未中奖',precent: 25},])const outBox = ref(null)const textAll = ref([]);const divAll = ref([]);const isFlag = ref(true); //防止重复点击抽奖按钮const timer = ref(null);const rotateDeg = ref(0); //计算旋转度数 360 / 总数量(awardList的数量)// 权重 获奖概率 2const weight = ref([5, 10, 20, 30, 45, 60, 75, 100])onMounted(() => {rotateDeg.value = (360 / awardList.value.length).toFixed(2)textAll.value = document.querySelectorAll('text')divAll.value = document.querySelectorAll('.out-box > div')outBox.value.style.transform = "rotate(" + rotateDeg.value + "deg)"for (let i = 0; i < awardList.value.length; i++) {divAll.value[i].style.transform = "rotate(" + i * rotateDeg.value + "deg)"}})const awardStart = () => {if (isFlag.value) {// 不考虑概率问题 ---1// let random = parseInt(Math.random() * 8)// getAward( rotateDeg.value - (rotateDeg.value * random), awardList.value[random].name)// 数组权重计算概率 ---2// let random = parseInt(Math.random() * 100);// let randomWeight = weight.value.concat(random);// let randomSort = randomWeight.sort((a,b) => {// 	return a - b;// })// let randomIndex = randomSort.indexOf(random);// // 向逆时针旋转// getAward( rotateDeg.value - (rotateDeg.value * randomIndex), awardList.value[randomIndex].name)// 用百分比计算中奖概率问题(随机数在概率值之间的个数)---3let percentTotal = awardList.value.reduce((sum, per) => sum + per.precent, 0);let random = parseInt(Math.random() * percentTotal);let sumPercent = 0; //概率累计值let percentIndex = 0;for (let i = 0; i < awardList.value.length; i++) {// 累加值为-- 5, 10, 20, 30, 45, 60, 75, 100sumPercent += awardList.value[i].precent;if (random < sumPercent) {percentIndex = i // 找到中奖奖项break}}// 向逆时针旋转getAward(rotateDeg.value - (rotateDeg.value * percentIndex), awardList.value[percentIndex].name)}}// 转到那个奖项const getAward = (dun, text) => {isFlag.value = false;console.log('dd', dun + '---' + text);let begin = 0;let basic = 360 * 5; //多少圈1800 / 360timer.value = setInterval(() => {if (begin >= (basic + dun)) {isFlag.value = true;clearInterval(timer.value)}outBox.value.style.transform = "rotate(" + begin + "deg)";// 缓慢停止的公式begin += Math.ceil((basic + dun - begin) * 0.1);// begin += 20}, 20)}const setColor = (index) => {let str = ''switch (index) {case 0:str = '#ff8d79';break;case 1:str = '#86ffa2';break;case 2:str = '#d0b4ff';break;case 3:str = '#66ebff';break;case 4:str = '#ffa6ce';break;case 5:str = '#e4feff';break;case 6:str = '#a097ff';break;case 7:str = '#eab5ff';break;case 8:str = '#ffa6ce';break;case 9:str = '#e4feff';break;case 10:str = '#a097ff';break;}return str}
</script>

3.实现效果图

注:该笔记主要用于自我研究学习,如有好的想法和改进之处请在评论区提出。

http://www.dtcms.com/a/327253.html

相关文章:

  • 【CSS3】录音中。。。
  • aspose word for java 使用书签进行内容填充和更新
  • AppStorageV2:鸿蒙全局状态管理详解-ArkUI本地存储
  • django 如何读取项目根目录下的文件内容
  • Python常用的5种中文分词工具
  • 力扣 hot100 Day71
  • Claude Code,Gemini CLI,Trae-agent, Qwen Code 使用对比及感受
  • 【数据分享】2020-2022年我国乡镇的逐日最高气温数据(Shp/Excel格式)
  • ABAC 权限策略扩展
  • 在达梦数据库中使用group by 命令报错问题
  • MCU中的液晶显示屏LCD(Liquid Crystal Display)控制器
  • Python 正则表达式 re.findall()
  • special topic 11 (1)
  • 【Linux系统】详解Ext2,文件系统
  • 打印流水号条形码
  • 标注工具组件功能文档
  • 如何将新建的Anaconda虚拟环境导入Juputer内核中?
  • Spring Boot项目通过RestTemplate调用三方接口详细教程
  • 系统架构设计师备考之架构设计实践知识
  • 完整反作弊系统架构(技术讲解)
  • 如何解决Unexpected token ‘<’, “<!doctype “… is not valid JSON 报错问题
  • MyBatis持久层实现
  • 人工智能概念:常见的大模型微调方法
  • Web学习笔记5
  • Java设计模式-快速入门
  • LeetCode算法领域经典入门题目之“Two Sum”问题
  • 1.4.1 副驾驶(Copilot)模式:让人工智能大模型成为你的指导和建议者
  • 从零开始之stm32之CAN通信
  • 聚合搜索中的设计模式
  • 鲲鹏arm服务器安装neo4j社区版,实现图书库自然语言检索基础