news 2026/5/13 1:27:10

单计时器的简单抽奖与相关扩展

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
单计时器的简单抽奖与相关扩展

首先来看一个简单的列子 是一个固定选项的抽奖页面 最终实现的效果是点击开始按钮之后会随机让一个单元格的背景色变成黄色 是一个很简单的抽奖 css样式部分小伙伴门可以自行调整

简单抽奖

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><divid="app"><buttonclass="btn">start</button><divclass="container"><divclass="basis-box">1</div><divclass="basis-box">2</div><divclass="basis-box">3</div><divclass="basis-box">4</div><divclass="basis-box">5</div><divclass="basis-box">6</div></div></div></body><script>constbtn=document.querySelector('.btn');//获取按钮//获取所有格子constcellList=document.getElementsByClassName('basis-box');letindex=0;//记录当前显示的cell索引// 添加点击事件btn.addEventListener('click',function(){cellList[index].classList.remove("highlight")index=Math.floor(Math.random()*cellList.length);cellList[index].classList.add("highlight")});</script><style>body{width:100vw;/* 占满窗口 */padding:0;}#app{width:100%;display:flex;flex-direction:column;align-items:center;}/* 按钮的样式 */.btn{width:60px;height:40px;}.container{display:flex;flex-direction:row;/* 横向排列每一个cell */font-size:28px;margin-top:10px;margin-bottom:10px;}.basis-box{display:flex;justify-content:center;/* 垂直居中 */align-items:center;/* 水平居中 */width:100px;height:100px;margin-left:10px;border:2px solid black;/* 边框 */}/* 用来表示选项的类 */.highlight{background-color:yellow;}</style></html>

这样就实现了一个简单的抽奖 但是这样的没有灵魂(好看的动画效果)这里只展示js的具体逻辑效果 css 的可以自行定义

具体实现

想要实现动画效果也就是实现随着时间变化速度也跟随一起变化的效果自然需要计时器,但是计时器多了会造成严重的卡顿,故此可以使用一个计时器实现这个效果。
实现思路如下:

  • 增加速度变量
  • 让计时器按照一定的tick进行
  • 速度可以使用时间 也可以使用计数器
    本文使用计数器实现速度变化 类似于我的世界的tick设计

像是这个样子 就可以实现一个简单的往复运动的抽奖但是有个问题 这个每次都会落到一个方块上

btn.addEventListener('click',function(){updateCell();});constupdateCell=()=>{letpreIndex=0;lettickCount=0;//记录已经更新的次数letcurInterval=2;//当前间隔letpreUpdateTick=0;//上次更新的tick数// 初始化第一个高亮cellList[index].classList.remove("highlight");consttimer=setInterval(()=>{tickCount++;if(tickCount-preUpdateTick>=curInterval){preUpdateTick=tickCount;curInterval=computedInterval(tickCount);// 更新高亮显示cellList[index].classList.remove("highlight");// 使用数学公式实现往复高亮index=Math.abs((preIndex++%(2*cellList.length-2))-(cellList.length-1));cellList[index].classList.add("highlight");}if(tickCount>=maxTick){clearInterval(timer);console.log('动画结束');return;}},tick);}constcomputedInterval=(tickCount)=>{if(tickCount<maxTick/3){return2;}elseif(tickCount<(maxTick/3)*2){return5;}elseif(tickCount<maxTick){return7;}}

可以给这个抽奖添加一个随机的初始位置实现随机的效果,并且可以优化一下现在的动画变动效果 现在的略显卡顿 tick也就是帧率 调小之后会变得更加流畅

改动之后的间隔计算: 增加阶段机制 让其更像是游戏里的抽奖 具体数值可以自己调整

constcomputedInterval=(tickCount)=>{constprogress=tickCount/maxTick;// 使用缓动函数实现更自然的减速效果if(progress<0.15){// 一阶段:0-15%return1+progress*20;// 1 -> 4}elseif(progress<0.35){// 二阶段:15%-35%constp=(progress-0.15)/0.2;return4+p*8;// 4 -> 12}elseif(progress<0.6){// 三阶段:中速 (35%-60%)constp=(progress-0.35)/0.25;return12+p*13;// 12 -> 25}elseif(progress<0.85){// 四阶段:慢速 (60%-85%)constp=(progress-0.6)/0.25;return25+p*20;// 25 -> 45}else{// 五阶段:85%-100%constp=(progress-0.85)/0.15;return45+p*35;// 45 -> 80}}

新的更新函数 增加了一个随机初始位置 并且增加一个随机是否反向运动增加随机性 这样的抽奖看起来更加的灵动

constupdateCell=()=>{// 随机起始位置letpreIndex=Math.floor(Math.random()*cellList.length);lettickCount=0;//记录已经更新的次数letcurInterval=1;//初始间隔letpreUpdateTick=0;//上次更新的tick数// 随机决定是否反向运动letdirection=Math.random()>0.5?1:-1;if(direction===-1){preIndex=cellList.length-1-preIndex;}// 初始化第一个高亮cellList[index].classList.remove("highlight");index=preIndex;cellList[index].classList.add("highlight");consttimer=setInterval(()=>{// 同上}}

扩展建议:

动态增加/删除格子

可以在抽奖过程中或开始前动态调整格子数量,让游戏更具灵活性:

<!-- 添加控制按钮 --><divclass="controls"><buttonid="addCellBtn">+ 添加格子</button><buttonid="removeCellBtn">- 删除格子</button></div>
// 动态添加格子constaddCell=()=>{constnewCell=document.createElement('div');newCell.className='basis-box';newCell.textContent=cellList.length+1;container.appendChild(newCell);cellList=document.getElementsByClassName('basis-box');};// 动态删除格子(至少保留2个)constremoveCell=()=>{if(cellList.length>2){container.removeChild(container.lastElementChild);cellList=document.getElementsByClassName('basis-box');// 如果当前索引超出范围,重置为0if(index>=cellList.length){index=0;}}};document.getElementById('addCellBtn').addEventListener('click',addCell);document.getElementById('removeCellBtn').addEventListener('click',removeCell);

自定义格子内容

允许用户为每个格子设置自定义文本或图片:

// 双击格子编辑内容cellList.forEach((cell,idx)=>{cell.addEventListener('dblclick',()=>{constnewText=prompt(`请输入第${idx+1}个格子的内容:`,cell.textContent);if(newText!==null&&newText.trim()!==''){cell.textContent=newText;}});});

多种动画模式

提供不同的动画效果供用户选择:

constanimationModes={// 往复运动(默认)bounce:(counter,length)=>{returnMath.abs((counter%(2*length-2))-(length-1));},// 单向循环loop:(counter,length)=>{returncounter%length;},// 随机跳动random:(counter,length)=>{returnMath.floor(Math.random()*length);},// 螺旋式减速spiral:(counter,length,maxTick)=>{constprogress=counter/maxTick;constspeed=1+Math.pow(progress,3)*10;returnMath.floor(counter/speed)%length;}};// 使用示例constmode='bounce';// 可切换index=animationModes[mode](preIndex++,cellList.length,maxTick);

概率控制系统

为不同格子设置不同的中奖概率:

// 定义每个格子的权重(概率)constweights=[10,20,30,15,15,10];// 数值越大,概率越高// 根据权重随机选择最终结果constweightedRandom=()=>{consttotalWeight=weights.reduce((sum,w)=>sum+w,0);letrandom=Math.random()*totalWeight;for(leti=0;i<weights.length;i++){random-=weights[i];if(random<=0){returni;}}returnweights.length-1;};// 在updateCell中使用constfinalIndex=weightedRandom();// ... 计算总步数时以finalIndex为终点
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 19:46:28

权威发布:智慧园区数字孪生解决方案提供商Top10排行榜及竞争力分析

随着智慧城市建设的纵深发展&#xff0c;智慧园区作为城市数字化治理的“微缩单元”和“试验田”&#xff0c;正迎来新一轮的技术革新。数字孪生技术通过构建物理园区的虚拟镜像&#xff0c;实现了从“人找事”到“事找人”的管理模式变革。基于2025至2026年度的市场表现、技术…

作者头像 李华
网站建设 2026/4/11 6:04:09

从英文焦虑到中文自信:Axure RP汉化完全指南

从英文焦虑到中文自信&#xff1a;Axure RP汉化完全指南 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界…

作者头像 李华
网站建设 2026/4/20 1:18:35

3个核心突破:用ObsPy解决地震数据处理的效率与兼容性难题

3个核心突破&#xff1a;用ObsPy解决地震数据处理的效率与兼容性难题 【免费下载链接】obspy ObsPy: A Python Toolbox for seismology/seismological observatories. 项目地址: https://gitcode.com/gh_mirrors/ob/obspy 地震学研究长期面临数据处理效率低下、格式兼容…

作者头像 李华
网站建设 2026/5/8 5:39:38

解锁开源模拟器跨平台体验:Ryujinx全攻略

解锁开源模拟器跨平台体验&#xff1a;Ryujinx全攻略 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx Ryujinx作为一款用C#编写的实验性Nintendo Switch模拟器&#xff0c;凭借其开源特…

作者头像 李华
网站建设 2026/4/25 14:05:00

僵尸事务阻塞生产库

僵尸事务阻塞生产库&#xff1a;数据库写操作全部卡死的排查与处理 背景 某天下午三点&#xff0c;监控突然告警&#xff1a;API 响应时间从正常的 50ms 飙升到 30 秒&#xff0c;大量请求超时。 查看应用日志&#xff0c;报错集中在数据库写操作&#xff1a; PDOException: SQ…

作者头像 李华
网站建设 2026/4/13 1:56:06

Visio进阶:绘制可伸缩的深度神经网络卷积块并实现无缝拼接

1. 为什么需要可伸缩的卷积块图表&#xff1f; 在绘制深度神经网络架构图时&#xff0c;卷积块是最基础的组成单元。传统做法是直接复制粘贴相同尺寸的立方体&#xff0c;但当我们需要表示不同宽度的卷积层&#xff08;比如不同通道数的卷积核&#xff09;时&#xff0c;简单拉…

作者头像 李华