用 HTML、CSS 和 JavaScript 实现抽奖转盘效果
顺序抽奖
前言
这段代码实现了一个简单的抽奖转盘效果。页面上有一个九宫格布局的抽奖区域,周围八个格子分别放置了不同的奖品名称,中间是一个 “开始抽奖” 的按钮。点击按钮后,抽奖区域的格子会快速滚动,颜色不断变化,模拟抽奖过程。经过一定圈数的滚动后,会随机停止在某一个格子上,弹出提示框显示中奖奖品。
效果展示


代码详情
HTML部分
<div class="box"><div class="div1">电脑</div><div class="div2">手机</div><div class="div3">音响</div><div class="div4">冰箱</div><div class="div5">空调</div><div class="div6">衣柜</div><div class="div7">沙发</div><div class="div8">地毯</div><button class="giftButton">开始抽奖</button>
</div>
CSS部分
* {margin: 0;padding: 0;
}.box {background-color: lightgray;width: 340px;height: 340px;position: relative;
}.box div {background-color: cadetblue;width: 100px;height: 100px;text-align: center;line-height: 100px;
}.div1 {position: absolute;top: 10px;left: 10px;
}/* 其他 .divX 类的样式省略,它们类似地设置了不同的 top 和 left 值来定位 */.giftButton {position: absolute;width: 100px;height: 100px;top: 120px;left: 120px;border-radius: 10px;background-color: navajowhite;
}
JS部分
初始化声明
boxCenter:通过document.getElementsByClassName('box')[0]获取到类名为box的元素,这个元素是整个抽奖区域的容器。allGift:使用boxCenter.getElementsByTagName('div')获取boxCenter内的所有div元素,这些div元素代表了各个奖品格子。giftButtons:通过document.getElementsByClassName('giftButton')[0]获取 “开始抽奖” 按钮元素,后续会为它添加点击事件。k:作为奖品的下标,用于标记当前高亮显示的奖品格子。time:旋转时间间隔,初始值为 500 毫秒,后续会根据抽奖过程动态调整。count:记录抽奖过程中转过的圈数,初始值为 0。inter:用于存储定时器,方便后续清除和重新设置定时器。random:存储随机生成的中奖下标,初始值为 0。
//获取box
let boxCenter = document.getElementsByClassName('box')[0];
//获取boxcenter里的所有的div元素
let allGift = boxCenter.getElementsByTagName('div');
//获取到抽奖按钮,后续帮点击事件
let giftButtons = document.getElementsByClassName('giftButton')[0];
//充当奖品的下标
let k = 0;
// 旋转时间间隔
let time = 500;
//圈数,就是转动的圈数
let count = 0;
//存定时器的
let inter;
//随机的数(中奖的下标)
let random = 0;
点击按钮事件
- 为
giftButtons按钮添加onclick事件处理函数。 - 当点击按钮时,将当前
k对应的奖品格子背景颜色设置为黄色,表示高亮显示。 - 使用
Math.random()生成一个 0 到 1 之间的随机数,乘以allGift.length得到一个随机范围在 0 到奖品数量之间的数,再使用Math.floor()向下取整,得到一个随机的中奖下标random。 - 使用
setInterval()函数设置一个定时器,每隔time毫秒执行一次autoScroll函数,开始抽奖滚动过程。
//上点击事件
giftButtons.onclick = function() {//奖品的下标k变颜色 allGift[k].style.backgroundColor = 'yellow';// 先生成一个随机数,然后*box里的所有div的数量,再向下取整random = Math.floor(Math.random() * allGift.length);//设定时器inter = setInterval(autoScroll, time);
}
滚动函数
- 奖品格子切换:
- 如果
k小于allGift.length - 1,说明还没有转到最后一个奖品格子,将k加 1,把上一个奖品格子的背景颜色变回cadetblue,当前k对应的格子背景颜色设置为黄色。 - 如果
k等于或大于allGift.length - 1,说明转到了最后一个奖品格子,将k重置为 0,代表开始下一圈,同时圈数count加 1,把上一圈最后一个奖品格子的背景颜色变回cadetblue,当前k对应的格子背景颜色设置为黄色。
- 如果
- 滚动速度调整:
- 当圈数
count小于 3 时,每次将time减去 100 毫秒,让滚动速度变快,但最快不超过 100 毫秒。 - 当圈数
count大于等于 3 时,每次将time加上 100 毫秒,让滚动速度变慢,但最慢不超过 300 毫秒。
- 当圈数
- 中奖判断与处理:
- 先使用
clearInterval(inter)清除当前的定时器。 - 如果随机生成的中奖下标
random等于当前的k且圈数count大于 4,说明抽奖停止,弹出提示框显示中奖的奖品名称。 - 否则,重新设置定时器,继续滚动,直到满足中奖条件。
- 先使用
function autoScroll() {//k小于长度 代表转到最后一个元素了 if (k < allGift.length - 1) {k++;//上一个奖品变回原色allGift[k - 1].style.backgroundColor = 'cadetblue';//当前索引下标变红allGift[k].style.backgroundColor = 'yellow';//k比长度长的话代表该转第二圈了} else {//重新让k=0下标, 下一次循环k = 0;//该转下一圈的话,圈数+1count++;//上一圈的最后一个奖品变回原色allGift[allGift.length - 1].style.backgroundColor = 'cadetblue';//当前索引下标变红allGift[k].style.backgroundColor = 'yellow';}if (count < 3) {//圈数小于5 ,每次都-100 让他变快变快time -= 100;//限制条件:最快滚动就是0.2秒if (time < 100) {time = 100;}//最外面的否则。就是圈数大于} else {//让他变慢time += 100;//限制条件:最慢就是2秒滚动一次if (time > 300) {time = 300;}}//判断中奖的是啥 和 确认转的圈数clearInterval(inter);if (random == k && count > 4) {//提示用户alert('🎉恭喜你,中奖的是🎉:' + '👉👉' + allGift[k].innerHTML + '👈👈');} else {//清除定时器//在设置一个定时器9inter = setInterval(autoScroll, time);}
}
随机抽奖
随机抽奖即为滚动的格子为随机的。
代码总览
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>抽奖页面</title><style>/* 全局样式重置 */* {margin: 0;padding: 0;}/* 抽奖容器样式 */.box {background-color: lightgray;width: 340px;height: 340px;position: relative;}/* 奖品方块样式 */.box div {background-color: cadetblue;width: 100px;height: 100px;text-align: center;line-height: 100px;}/* 各个奖品方块定位样式 */.div1 {position: absolute;top: 10px;left: 10px;}.div2 {position: absolute;top: 10px;left: 120px;}.div3 {position: absolute;top: 10px;left: 230px;}.div4 {position: absolute;top: 120px;left: 230px;}.div5 {position: absolute;top: 230px;left: 230px;}.div6 {position: absolute;top: 230px;left: 120px;}.div7 {position: absolute;top: 230px;left: 10px;}.div8 {position: absolute;top: 120px;left: 10px;}/* 抽奖按钮样式 */.giftButton {position: absolute;width: 100px;height: 100px;top: 120px;left: 120px;border-radius: 10px;background-color: navajowhite;}#bigAlert {display: flex;position: fixed;/* z-index: 1; *//* left: 0; */top: 0;width: 100%;height: 100%;/* overflow: auto; */background-color: rgba(0, 0, 0, 0.4);align-content: center;}.alertContent {display: flex;justify-content: space-around;align-items: center;background-color: white;border-radius: 10px;/* margin: 15%; *//* padding: 20px; *//* border: 1px solid #888; */width: 300px;height: 100px;/* margin-left: auto;margin-right: auto; */margin: auto;}.buttonAlert {padding: 10px;color: black;background-color: gold;border: none;border-radius: 10px;cursor: pointer;}.buttonAlert:hover {background-color: #609EA0;color: blue;transition: 0.3s ease;}.mengban {background-color: rgba(0, 0, 0, 0.5);width: 100%;height: 100%;/* z-index: 2; */position: absolute;top: 0px;left: 0px;border-radius: 8px;}</style></head><body><div class="box"><div class="div1">电脑</div><div class="div2">手机</div><div class="div3">音响</div><div class="div4">冰箱</div><div class="div5">空调</div><div class="div6">衣柜</div><div class="div7">沙发</div><div class="div8">地毯</div><button class="giftButton"><span class="mengban" style="display: none;" readonly></span>开始抽奖</button></div><div id="bigAlert" style="display: none;"><div class="alertContent"><span id="alertMessage"></span><button class="buttonAlert" onclick="closeAlert()">确定</button></div></div><script>// 显示弹窗的function showAlert(a) {//先获取到大的divlet alertDiv = document.getElementById('bigAlert');//在获取span标签let messageSpan = document.getElementById('alertMessage');// 传参(中奖提示)// messageSpan.innerHTML = `<span style="color: red;">${a}</span>`;;//中奖提示(模板字符串)let startIndex = a.indexOf("中奖的是") + "中奖的是".length;let highlightedPart = a.slice(startIndex);messageSpan.innerHTML = `<span>${a.slice(0, startIndex)}<span style="color: red; font-weight: bold;">${highlightedPart}</span></span>`;//上面隐藏了 现在在显示出来alertDiv.style.display = 'block';}showAlert('aaaaaaaaaaaa');//关闭弹窗的function closeAlert() {//获取到大divlet alertDiv = document.getElementById('bigAlert');//隐藏alertDiv.style.display = 'none';}// 获取boxlet boxCenter = document.getElementsByClassName('box')[0];// 获取boxcenter里的所有的div元素let allGift = boxCenter.getElementsByTagName('div');// 获取到抽奖按钮,后续绑定点击事件let giftButtons = document.getElementsByClassName('giftButton')[0];// 充当所有的奖品的下标let giftIndex = 0;// 旋转时间间隔let time = 200;// 存定时器的let inter;// 本次抽奖的随机圈数let countTotal;let mengban = document.getElementsByClassName('mengban')[0];//闪动次数let bulingBuling = 0;// 点击事件giftButtons.onclick = function() {bulingBuling = 0;// 在数100-200格之间 。随机生成格数countTotal = Math.floor(Math.random() * 10 + 1) + 10;// 设定时器inter = setInterval(autoScroll, time);//蒙版显示。标签上隐藏了mengban.style.display = 'block';//清除点击事件 ,为了抽奖的时候不能再点抽奖按钮giftButtons.onclick = null;}//这个函数会在定时器内被反复调用function autoScroll() {//每次被调用这个函数 闪动次数+1bulingBuling++;// 随机选择下一个要变色显示的奖品索引(不按照顺序)let nextIndex;nextIndex = Math.floor(Math.random() * allGift.length);// 循环数组中的每一个元素 让他们颜色统一for (let i = 0; i < allGift.length; i++) {allGift[i].style.backgroundColor = 'cadetblue';}// 把 全部div 中挑出来的随机索引下标变黄allGift[nextIndex].style.backgroundColor = 'yellow';// 判断闪的格,是否等于上面要求的格数if (bulingBuling == countTotal) {mengban.style.display = 'none';//满足就清除定时器clearInterval(inter);// 提示用户showAlert('🎉恭喜你,中奖的是🎉:' + ' ' + allGift[nextIndex].innerHTML);//========================重新绑定点击事件============================================giftButtons.onclick = function() {bulingBuling = 0;// 在数100-200格之间 。随机生成格数countTotal = Math.floor(Math.random() * 10 + 1) + 10;// 设定时器inter = setInterval(autoScroll, time);mengban.style.display = 'block';giftButtons.onclick = null;}}}</script></body></html>
功能实现差异
第一段代码
- 滚动规则:奖品格子按照顺序依次滚动,从第一个格子开始,逐个向后滚动,当到达最后一个格子后,重新从第一个格子开始滚动,形成循环滚动的效果。
- 速度控制:在抽奖开始的前几圈(圈数小于 3),滚动速度逐渐加快,最快达到每 100 毫秒滚动一次;之后滚动速度逐渐变慢,最慢为每 300 毫秒滚动一次。
- 中奖判断:当随机生成的中奖下标与当前滚动到的格子下标相等,并且已经滚动超过 4 圈时,抽奖停止,弹出中奖提示框。
- 提示方式:使用浏览器默认的
alert函数弹出提示框,显示中奖信息
第二段代码
- 滚动规则:奖品格子随机闪烁,每次闪烁时,随机选择一个奖品格子改变颜色,不按照顺序进行滚动。
- 速度控制:滚动速度固定为每 200 毫秒闪烁一次,没有动态调整速度的过程。
- 中奖判断:预先随机生成一个 11 - 20 之间的闪烁次数(
countTotal),当闪烁次数达到这个随机值时,抽奖停止,弹出中奖提示框。 - 提示方式:自定义了一个模态框,通过修改模态框的
display属性来显示和隐藏,并且对中奖信息中的奖品名称进行了样式处理(红色加粗)。
相关文章:
用 HTML、CSS 和 JavaScript 实现抽奖转盘效果
顺序抽奖 前言 这段代码实现了一个简单的抽奖转盘效果。页面上有一个九宫格布局的抽奖区域,周围八个格子分别放置了不同的奖品名称,中间是一个 “开始抽奖” 的按钮。点击按钮后,抽奖区域的格子会快速滚动,颜色不断变化…...
R语言绘制有向无环图(DAG)
有向无环图(Directed Acyclic Graph,简称DAG)是一种特殊的有向图,它由一系列顶点和有方向的边组成,其中不存在任何环路。这意味着从任一顶点出发,沿着箭头方向移动,你永远无法回到起始点。 从流…...
报错Too many open files
1、先查看系统最大打开文件数 # 查看当前系统打开文件最大数 # ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signal…...
Spring Web MVC基础第一篇
目录 1.什么是Spring Web MVC? 2.创建Spring Web MVC项目 3.注解使用 3.1RequestMapping(路由映射) 3.2一般参数传递 3.3RequestParam(参数重命名) 3.4RequestBody(传递JSON数据) 3.5Pa…...
129.求根节点到叶节点数字之和(遍历思想)
Problem: 129.求根节点到叶节点数字之和 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的先序遍历) 直接利用二叉树的先序遍历,将遍历过程中的节点值先利用字符串拼接起来遇到根节点时再转为数字并累加起来,在归的过程中…...
unity中的动画混合树
为什么需要动画混合树,动画混合树有什么作用? 在Unity中,动画混合树(Animation Blend Tree)是一种用于管理和混合多个动画状态的工具,包括1D和2D两种类型,以下是其作用及使用必要性的介绍&…...
AWS EMR使用Apache Kylin快速分析大数据
在AWS Elastic MapReduce(EMR)集群上部署和使用Apache Kylin,以实现对大规模数据集的快速分析,企业可以充分利用云计算的强大资源和Kylin的数据分析能力,实现快速、高效的数据分析。以下是该案例的详细步骤和要点&…...
MySQL存储过程和存储函数_mysql 存储过 call proc_stat_data(3,null)
2)很难调试存储过程。只有少数数据库管理系统允许调试存储过程。不幸的是,MySQL不提供调试存储过程的功能。 1.2 数据准备 创建数据库: DEFAULT CHARACTER SET utf8; use test;这里记得设置编码! 创建测试表: DROP…...
spacemacs gnuplot
个人博客地址:spacemacs gnuplot | 一张假钞的真实世界 环境 Ubuntu 16.10Emacs 24 安装过程 spacemacs安装 安装Emacs sudo apt-get install emacs 安装spacemacs (1)如果已经存在Emacs配置文件,首先备份: c…...
Flink2支持提交StreamGraph到Flink集群
最近研究Flink源码的时候,发现Flink已经支持提交StreamGraph到集群了,替换掉了原来的提交JobGraph。 新增ExecutionPlan接口,将JobGraph和StreamGraph作为实现。 Flink集群Dispatcher也进行了修改,从JobGraph改成了接口Executio…...
Kotlin 使用 Springboot 反射执行方法并自动传参
在使用反射的时候,执行方法的时候在想如果Springboot 能对需要执行的反射方法的参数自动注入就好了。所以就有了下文。 知识点 获取上下文通过上下文获取 Bean通过上下文创建一个对象,该对象所需的参数由 Springboot 自己注入 创建参数 因为需要对反…...
索罗斯的“反身性”(Reflexivity)理论:市场如何扭曲现实?(中英双语)
索罗斯的“反身性”(Reflexivity)理论:市场如何扭曲现实? 一、引言:市场是镜子,还是哈哈镜? 在传统经济学中,市场通常被认为是一个理性、有效的反映现实的系统。按照经典经济学理论…...
Vue 入门到实战 七
第7章 渲染函数 目录 7.1 DOM树 7.2 什么是渲染函数 7.3 h()函数 7.3.1 基本参数 7.3.2 约束 7.3.3 使用JavaScript代替模板功能 7.1 DOM树 7.2 什么是渲染函数 在多数情况下,Vue推荐使用模板template来创建HTML。然而在一些应用场景中,需要使用J…...
系统学习算法: 专题八 二叉树中的深搜
深搜其实就是深度优先遍历(dfs),与此相对的还有宽度优先遍历(bfs) 如果学完数据结构有点忘记,如下图,左边是dfs,右边是bfs 而二叉树的前序,中序,后序遍历都可…...
进程、线程、内存和IO模型的概念详解
进程、线程、内存和IO模型的概念详解 1 进程与线程1.1 进程1.1.1 进程分类1.1.2 进程的状态和转换1.1.3 僵尸进程和孤儿进程的区别1.1.4 进程之间的通信1.1.5 用户态和内核态1.1.6 用户空间和内核空间 1.2 线程1.2.1 线程的状态和转换1.2.2 进程与线程的区别 1.3 多进程和多线程…...
DeepSeek:AI领域的创新先锋
在人工智能领域,DeepSeek正以其独特的创新技术引领着行业的发展。作为一款高性能、低成本的AI模型,DeepSeek在架构设计、训练优化和应用场景等多个方面都展现出了显著的创新点。这些创新不仅使其在技术上取得了突破,也为AI的普及化和应用拓展…...
Labelme转Voc、Coco
Q:在github找的cv代码基本都是根据现有且流行的公共数据集格式组织的训练数据集,这导致我使用labelme标注好之后需要我们重新组织数据集 labelme2coco #!/usr/bin/env pythonimport argparse import collections import datetime import glob import j…...
pytorch实现变分自编码器
人工智能例子汇总:AI常见的算法和例子-CSDN博客 变分自编码器(Variational Autoencoder, VAE)是一种生成模型,属于深度学习中的无监督学习方法。它通过学习输入数据的潜在分布(Latent Distribution)&…...
使用 Numpy 自定义数据集,使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数
1. 导入必要的库 首先,导入我们需要的库:Numpy、Pytorch 和相关工具包。 import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import accuracy_score, recall_score, f1_score2. 自定义数据集 …...
JVM方法区
一、栈、堆、方法区的交互关系 二、方法区的理解: 尽管所有的方法区在逻辑上属于堆的一部分,但是一些简单的实现可能不会去进行垃圾收集或者进行压缩,方法区可以看作是一块独立于Java堆的内存空间。 方法区(Method Area)与Java堆一样,是各个…...
【Python】第七弹---Python基础进阶:深入字典操作与文件处理技巧
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】【Python】 目录 1、字典 1.1、字典是什么 1.2、创建字典 1.3、查找 key 1.4、新增/修改元素 1.5、删除元素 1.6、遍历…...
指导初学者使用Anaconda运行GitHub上One - DM项目的步骤
以下是指导初学者使用Anaconda运行GitHub上One - DM项目的步骤: 1. 安装Anaconda 下载Anaconda: 让初学者访问Anaconda官网(https://www.anaconda.com/products/distribution),根据其操作系统(Windows、M…...
在实际开发中,如何正确使用 INT(1) 和 INT(10)
在实际开发中,如何正确使用 INT(1) 和 INT(10) 前言 在数据库设计和开发过程中,数据类型的选择至关重要。 最近,我在工作中遇到了一个关于MySQL中INT类型的误解问题,这让我意识到很多开发者对INT类型的理解存在误区。 本文将深…...
像接口契约文档 这种工件,在需求 分析 设计 工作流里面 属于哪一个工作流
οゞ浪漫心情ゞο(20***328) 2016/2/18 10:26:47 请教一下,像接口契约文档 这种工件,在需求 分析 设计 工作流里面 属于哪一个工作流? 潘加宇(35***47) 17:17:28 你这相当于问用例图、序列图属于哪个工作流,看内容。 如果你的&quo…...
GAMES101学习笔记(六):Geometry 几何(基本表示方法、曲线与曲面、网格处理)
文章目录 几何的表示方法隐式几何 Implicit Geometry代数曲面(Algebraic surface)构造实体几何CSG(Constructive Solid Geometry)距离函数(Distance Function)水平集方法(Level Set Methods)分型几何(Fractal) 显式几何 Explicit Geometry点云(Point Cloud)多边形网格(Polygon …...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.24 随机宇宙:生成现实世界数据的艺术
1.24 随机宇宙:生成现实世界数据的艺术 目录 #mermaid-svg-vN1An9qZ6t4JUcGa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-vN1An9qZ6t4JUcGa .error-icon{fill:#552222;}#mermaid-svg-vN1An9qZ6t4JUc…...
深入解析:一个简单的浮动布局 HTML 示例
深入解析:一个简单的浮动布局 HTML 示例 示例代码解析代码结构分析1. HTML 结构2. CSS 样式 核心功能解析1. 浮动布局(Float)2. 清除浮动(Clear)3. 其他样式 效果展示代码优化与扩展总结 在网页设计中,浮动…...
爬虫基础(三)Session和Cookie讲解
目录 一、前备知识点 (1)静态网页 (2)动态网页 (3)无状态HTTP 二、Session和Cookie 三、Session 四、Cookie (1)维持过程 (2)结构 正式开始说 Sessi…...
HTMLCSS :下雪了
这段代码创建了一个动态的雪花飘落加载动画,通过 CSS 技术实现了雪花的下落和消失效果,为页面添加了视觉吸引力和动态感。 大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能…...
力扣 84. 柱状图中最大的矩形
🔗 https://leetcode.cn/problems/largest-rectangle-in-histogram 题目 给一个数组 num 表示位置 i 上圆柱的高度,求圆柱可以勾勒出的矩形的最大面积 思路 枚举圆柱 i,以该圆柱为高,计算其可以组成的矩形的最大面积。记录这过…...
