JavaScript实践:用Canvas开发一个可配置的大转盘抽奖功能

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。
🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。
🏆本文已收录于专栏:100个JavaScript的小应用。
🎉欢迎 👍点赞✍评论⭐收藏
文章目录
- 🚀一、引言
- 🚀二、开发思路
- 🚀三、代码实现
- 🔎3.1 HTML结构(index.html)
- 🔎3.2 CSS样式(style.css)
- 🔎3.3 JavaScript代码(script.css)
- 🍁3.3.1 配置中奖概率
- 🍁3.3.2 开发圆盘效果
- 🍁3.3.3 开发指针样式
- 🍁3.3.4 开发点击抽奖事件
- 🚀四、测试效果
- 🚀五、完整代码
- 🔎5.1 index.html
- 🔎5.2 style.css
- 🔎5.3 script.js
- 🚀六、总结
🚀一、引言
大转盘抽奖是一种常见的游戏方式,用户可以通过点击按钮让指针开始旋转,在经过一段时间后指针会停下来,显示用户中奖的奖项。本文将用
Javascript和HTML实现一个简单的大转盘抽奖功能。详细介绍实现思路和代码。
⭐⭐文末附完整代码⭐⭐
🚀二、开发思路
本文将使用JavaScript和HTML来实现一个简单的大转盘抽奖功能。具体步骤如下:
- 创建
HTML结构:使用HTML创建一个大转盘容器,包括转盘、指针和抽奖按钮。 - 使用
CSS样式:使用CSS样式来美化大转盘的外观,包括颜色、字体等。 - 使用
JavaScript编写抽奖逻辑:根据配置的奖项和概率,计算中奖结果,并设置指针的旋转动画效果。 - 绑定点击事件:为抽奖按钮绑定点击事件,点击按钮后开始抽奖逻辑。
- 弹出中奖内容:抽奖结束后,使用
alert弹窗显示中奖结果。
🚀三、代码实现
🔎3.1 HTML结构(index.html)
<div id="canvas"><canvas id="wheel" width="600" height="600"></canvas></div>
<button onclick="startSpin()">抽奖</button>
🔎3.2 CSS样式(style.css)
css样式主要定义圆盘和按钮的显示效果,核心代码如下:
#canvas {position: relative;
}.block {width: 200px;height: 200px;display: flex;justify-content: center;align-items: center;font-size: 20px;font-weight: bold;
}
🔎3.3 JavaScript代码(script.css)
🍁3.3.1 配置中奖概率
先定义一个配置数组,用于配置奖项的名称抽奖背景色以及中奖的概率,后面圆盘会根据这个显示出对应的效果。
const prizes = [{ text: '奖品1', color: '#f44336', probability: 0.2 },{ text: '奖品2', color: '#9c27b0', probability: 0.1 },{ text: '奖品3', color: '#3f51b5', probability: 0.15 },{ text: '奖品4', color: '#00bcd4', probability: 0.25 },{ text: '奖品5', color: '#4caf50', probability: 0.2 },{ text: '奖品6', color: '#000000', probability: 0.1 }
];
🍁3.3.2 开发圆盘效果
根据上面的配置,来开发出圆盘,主要用到Javascript进行编码。
function drawWheel() {ctx.clearRect(0, 0, canvas.width, canvas.height);let startAngle = 0;let endAngle = 0;for (let i = 0; i < prizes.length; i++) {startAngle = endAngle;endAngle = startAngle + (Math.PI * 2 * prizes[i].probability);ctx.beginPath();ctx.arc(centerX, centerY, radius, startAngle, endAngle, false);ctx.lineTo(centerX, centerY);ctx.fillStyle = prizes[i].color;ctx.fill();ctx.save();ctx.translate(centerX, centerY);ctx.rotate((startAngle + endAngle) / 2);ctx.fillStyle = 'white';ctx.font = '20px Arial';ctx.fillText(prizes[i].text, radius / 2, 0);ctx.restore();}
}
现在来预览一下圆盘效果,是不是还挺好看的。接下来继续开发指针及旋转中奖效果。

🍁3.3.3 开发指针样式
首先来一段css样式来安排一下指针效果:
#pointer {position: absolute;top: calc(50% - 5px);left: calc(50% - 2.5px);width: 5px;height: 30%;background-color: red;transform-origin: bottom center;transition: transform 5s ease-in-out;left: 300px;top: 120px;
}
把下面的div放到index.html里面去,显示效果如下图。
<div id="pointer"></div>

🍁3.3.4 开发点击抽奖事件
我们通过点击按钮来触发抽奖动作。当用户点击按钮时。开始旋转抽奖指针,并且在5秒后停止并显示中奖内容。主要js代码如下。
function spinWheel() {if (!spinning) {angle = angle % (Math.PI * 2);ctx.clearRect(centerX - 10, centerY - radius - 10, 20, radius + 20);ctx.save();ctx.translate(centerX, centerY);ctx.rotate(angle);ctx.beginPath();ctx.moveTo(-5, -radius - 5);ctx.lineTo(5, -radius - 5);ctx.lineTo(0, -radius - 15);ctx.closePath();ctx.fillStyle = 'red';ctx.fill();ctx.restore();angle += 0.1;requestAnimationFrame(spinWheel);}
}
// 开始抽奖逻辑
function startSpin() {if (!spinning) {genRandom()spinning = true;spinWheel();pointerRotate()setTimeout(stopSpin, 5000);}
}
// 指针开始旋转
function pointerRotate() {const pointer = document.getElementById('pointer');const rotation = 360 * random + 720;// 设置动画pointer.style.transform = 'rotateZ(' + rotation + 'deg)';pointer.style.pointerEvents = 'none';// 停止旋转并弹出中奖内容setTimeout(() => {pointer.style.pointerEvents = 'auto';}, 5000);
}
// 指针停止事件
function stopSpin() {spinning = false;const selectedPrize = getSelectedPrize();alert('中奖内容:' + selectedPrize.text);
}
// 根据旋转角度获取中奖内容
function getSelectedPrize() {let startAngle = 0;let endAngle = prizes[0].probability;for (let i = 0; i < prizes.length; i++) {if (random >= startAngle && random < endAngle) {return prizes[i];}startAngle = endAngle;endAngle += prizes[i + 1].probability;}
}
🚀四、测试效果
在实际场景中假设我们设计如下5个奖项。点击抽奖按钮,可以看到指针转动,5秒后停止并弹出中奖内容。
macbook 14pro,中奖概率10%。iPhone13,中奖概率30%。xiaomi手机,中奖概率20%。100元商城优惠券,中奖概率20%。感谢参与,中奖概率20%。
const prizes = [{ text: 'macbook14pro', color: '#f44336', probability: 0.1 },{ text: 'iPhone13', color: '#9c27b0', probability: 0.3 },{ text: 'xiaomi', color: '#3f51b5', probability: 0.2 },{ text: '100元优惠券', color: '#00bcd4', probability: 0.2 },{ text: '感谢参与', color: '#4caf50', probability: 0.2 },
];

🚀五、完整代码
🔎5.1 index.html
<!DOCTYPE html>
<html>
<head><title>大转盘抽奖</title><link rel="stylesheet" type="text/css" href="style.css">
</head>
<body><div id="canvas"><canvas id="wheel" width="600" height="600"></canvas><div id="pointer"></div></div><button onclick="startSpin()">抽奖</button><script type="text/javascript" src="script.js"></script>
</body>
</html>
🔎5.2 style.css
#canvas {position: relative;width: 600px;height: 600px;
}
#pointer {position: absolute;top: calc(50% - 5px);left: calc(50% - 2.5px);width: 5px;height: 30%;background-color: red;transform-origin: bottom center;transition: transform 5s ease-in-out;left: 300px;top: 120px;
}.block {width: 200px;height: 200px;display: flex;justify-content: center;align-items: center;font-size: 20px;font-weight: bold;
}
🔎5.3 script.js
const prizes = [{ text: 'macbook14pro', color: '#f44336', probability: 0.1 },{ text: 'iPhone13', color: '#9c27b0', probability: 0.3 },{ text: 'xiaomi', color: '#3f51b5', probability: 0.2 },{ text: '100元优惠券', color: '#00bcd4', probability: 0.2 },{ text: '感谢参与', color: '#4caf50', probability: 0.2 },
];const canvas = document.getElementById('wheel');
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = Math.min(canvas.width, canvas.height) / 2;
let angle = 0;
let spinning = false;function drawWheel() {ctx.clearRect(0, 0, canvas.width, canvas.height);let startAngle = 0;let endAngle = 0;for (let i = 0; i < prizes.length; i++) {startAngle = endAngle;endAngle = startAngle + (Math.PI * 2 * prizes[i].probability);ctx.beginPath();ctx.arc(centerX, centerY, radius, startAngle, endAngle, false);ctx.lineTo(centerX, centerY);ctx.fillStyle = prizes[i].color;ctx.fill();ctx.save();ctx.translate(centerX, centerY);ctx.rotate((startAngle + endAngle) / 2);ctx.fillStyle = 'white';ctx.font = '20px Arial';ctx.fillText(prizes[i].text, radius / 2, 0);ctx.restore();}
}function spinWheel() {if (!spinning) {angle = angle % (Math.PI * 2);ctx.clearRect(centerX - 10, centerY - radius - 10, 20, radius + 20);ctx.save();ctx.translate(centerX, centerY);ctx.rotate(angle);ctx.beginPath();ctx.moveTo(-5, -radius - 5);ctx.lineTo(5, -radius - 5);ctx.lineTo(0, -radius - 15);ctx.closePath();ctx.fillStyle = 'red';ctx.fill();ctx.restore();angle += 0.1;requestAnimationFrame(spinWheel);}
}function startSpin() {if (!spinning) {genRandom()spinning = true;spinWheel();pointerRotate()setTimeout(stopSpin, 5000);}
}function pointerRotate() {const pointer = document.getElementById('pointer');const rotation = 360 * random + 720;// 设置动画pointer.style.transform = 'rotateZ(' + rotation + 'deg)';pointer.style.pointerEvents = 'none';// 停止旋转并弹出中奖内容setTimeout(() => {pointer.style.pointerEvents = 'auto';}, 5000);
}function stopSpin() {spinning = false;const selectedPrize = getSelectedPrize();alert('中奖内容:' + selectedPrize.text);
}function getSelectedPrize() {let startAngle = 0;let endAngle = prizes[0].probability;for (let i = 0; i < prizes.length; i++) {if (random >= startAngle && random < endAngle) {return prizes[i];}startAngle = endAngle;endAngle += prizes[i + 1].probability;}
}var random = Math.random()function genRandom() {random = Math.random()
}drawWheel();
🚀六、总结
本文使用JavaScript和HTML实现了一个的大转盘抽奖功能。通过配置奖项和概率,用户可以根据自己的需要来设置抽奖的规则。点击抽奖按钮后,指针开始旋转,经过5秒后停止,并弹出中奖内容。
以上就是本文的具体思路和代码实现,通过这个示例,你可以了解到如何使用JavaScript和HTML来实现大转盘抽奖功能。希望对你有所帮助!实际的应用中,可以基于上面的内容修改。

今天的内容就到这里,我们下次见。
相关文章:
JavaScript实践:用Canvas开发一个可配置的大转盘抽奖功能
🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已…...
yay无法更新问题解决
背景 更新yay后,yay安装软件捞出问题,查的github上的都不靠谱。因此需要把yay的版本固定下,正常的11版本是可用的 解决方案 sudo pacman -S --needed git base-devel git clone https://aur.archlinux.org/yay.git cd yay makepkg -si # 注…...
C语言 — 动态内存管理(动态内存函数)
前言 本期分为三篇介绍动态内存管理相关内容,关注博主了解更多 博主博客链接:https://blog.csdn.net/m0_74014525 本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C程序的内存开辟区域 系列文章 第一篇ÿ…...
Visual ChatGPT:Microsoft ChatGPT 和 VFM 相结合
推荐:使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是Visual ChatGPT? Visual ChatGPT 是一个包含 Visual Foundation 模型 (VFM) 的系统,可帮助 ChatGPT 更好地理解、生成和编辑视觉信息。VFM 能够指…...
基于java理发店预约系统微信小程序设计与实现
摘要 多姿多彩的世界带来了美好的生活,行业的发展也是形形色色的离不开技术的发展。作为时代进步的发展方面,信息技术至始至终都是成就行业发展的重要秘密。不论何种行业,大到国家、企业,小到团体、个人都在多方位的结合信息化技术…...
【软件测试】大厂测工都是这样学习的,你get到了吗?
有不少的软件测试工程师站在“十字路口”迷茫、无助,找不到自己的方向。一切的迷茫都是因为想得太多而做的太少!每位软件测试行业从业者都能意识到目前自己面临的窘境,但能及时作出改变,顺应时代变化的人还是太少。多数人明明“泰…...
如何使用ONLYOFFICE+ffmpeg来给视频文件打马赛克
如何使用ONLYOFFICEffmpeg来给视频文件打马赛克 我这里之前写过很多关于ONLYOFFICE使用、安装的系列图文,也写过很多关于ffmpeg使用的图文,那么这次继续,把这两个开源软件放在一起,能碰撞出什么火花般的功能来。 这就是给视频文…...
003-依赖注入、属性赋值源码分析
目录 引入作用代码分析InstantiationAwareBeanPostProcessor#postProcessProperties()AutowiredAnnotationBeanPostProcessor查找注入点元数据给注入点注入属性 引入 之前我们了解到BeanDefinition到Bean,经历了 实例化属性赋值初始化 3个步骤现在详细分析下属性赋…...
Elasticsearch 商业启示
上月的“红帽事件”,说明开源软件的“客服模式”行不通,那么,开源软件如何赚钱呢?既不能卖软件,又不能卖支持服务,该怎么办呢?我现在的看法是,只剩下一种模式是可行的,开…...
C++/Qt 读写文件
之前写过两篇跟文件操作相关的博客,有兴趣也可以看一下: C语言读写文件 Qt关于文件路径的处理 先讲一些关于基础文本文件和二进制文件的读写操作,后续将会整理C/Qt关于ini、xml、json、xlsx相关文件的读写操作。 C 相比于C语言使用FILE文…...
linux服务器之-nethogs命令
文章目录 NetHogs 工具安装安装依赖包安装epel源安装Nethogs 使用 NetHogs 工具 NetHogs是一个小型的net top工具,不像大多数工具那样拖慢每个协议或者是每个子网的速度而是依照进程进行带宽分组。 安装 安装依赖包 yum install libpcap libpcap-devel epel-rel…...
《每天5分钟玩转kubernetes》读书笔记
笔记 概念 Pod是脆弱的,但应用是健壮的。 kubelet运行在Cluster所有节点上,负责启动Pod和容器。kubeadm用于初始化Cluster。kubectl是k8s命令行工具。通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件。 …...
【RabbitMQ】golang客户端教程4——路由(使用direct交换器)
路由 在上一教程中,我们构建了一个简单的日志记录系统。我们能够向许多接收者广播日志消息。 在本教程中,我们将向它添加一个特性-我们将使它能够只订阅消息的一个子集。例如,我们将只能将关键错误消息定向到日志文件(以节省磁盘…...
Shell脚本学习-for循环结构2
案例:通过脚本实现仅sshd、rsyslog、crond、network、sysstat服务在开机时自启动。 Linux系统在开机的服务通常工作在文本模式3级别,因此只需要查找3级别以上的开启的服务即可。查看命令: chkconfig --list |grep 3:on [rootvm1 ~]# chkco…...
vue 老项目 npm install 报错Python,c++等相关错误
老项目npm install 下载依赖包报错 解决方法: //下载python 1、 npm install --global --production windows-build-tools//配置环境 : 也可暂时不用配置,能用就不用配置(npm config set python "D:\Python27\python.exe&q…...
【c语言初级】c++基础
文章目录 1. C关键字2. 命名空间2.1 命名空间定义2.2 命名空间使用 3. C输入&输出4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类 5. 函数重载5.2 C函数重载的原理--名字修饰采用C语言编译器编译后结果 1. C关键字 C是在C的基础之上,容纳进去了面向对象编程思想…...
idea打开传统eclipse项目
打开传统web项目 1.打开后选择项目文件 2.选择项目结构 3.设置jdk版本 4.导入当前项目模块 5.选择eclipse 6. 设置保存目录 7.右键模块,添加spring和web文件 8. 设置web目录之类的,并且创建打包工具 9.如果有本地lib,添加为库 最后点击应用&…...
全国各城市-财政收入-一般预算收入-各项税收-个人所得税(1999-2020年)
个人所得税是一项反映国家财政状况和个人经济水平的重要数据。通过对全国各城市个人所得税数据的研究,可以提供研究者参考的有益信息。首先,个人所得税数据反映了不同城市居民的收入水平。通过对不同城市的个人所得税数据进行比较,可以了解不…...
【动态网页抓取】 :用Python抓取所有内容的指南
一、说明 您在抓取动态网页内容时是否得到了糟糕的结果?不仅仅是你。对于标准抓取工具来说,爬网动态数据是一项具有挑战性的任务(至少可以说)。这是因为当发出HTTP请求时,响应程序的某些部分JavaScript在后台运行&…...
Spring Boot数据访问基础知识与JDBC简单实现
目录 Spring Boot数据访问基础知识 Spring Data ORM JDBC JPA JDBC简单实现 步骤1:新建Maven项目,添加依赖 步骤2:配置数据源—让程序可以访问到 步骤3:配置数据源—让IDEA可以访问到 步骤4:添加数据库和表 …...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
