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:添加数据库和表 …...
如何像管理代码一样构建个人技能树:从知识管理到职业发展
1. 项目概述与核心价值最近在整理个人知识库和技能树时,发现了一个挺有意思的项目,叫mxyhi/ok-skills。乍一看,这像是一个个人仓库,但深入探究后,我发现它远不止是一个简单的代码托管。它更像是一个结构化的个人能力发…...
Claude Code Ultraplan 远程多代理规划全解析:AI Agent、CCR远程容器、异步规划、状态机、计划传送与企业级自动化治理
一、先说结论:Ultraplan 到底解决了什么痛点?Ultraplan 可以理解为一种“远程规划模式”:用户在本地终端发起一个复杂任务,系统把规划阶段卸载到远程 CCR 容器中执行。本地终端不再被长时间占住,远程端可以使用更强模型…...
音乐标签混乱的终结者:music-tag-web如何用3个步骤帮你重建完美音乐库
音乐标签混乱的终结者:music-tag-web如何用3个步骤帮你重建完美音乐库 【免费下载链接】music-tag-web 音乐标签编辑器,可编辑本地音乐文件的元数据(Editable local music file metadata.) 项目地址: https://gitcode.com/gh_mi…...
黑苹果配置不再难:Hackintool一站式解决方案让你15分钟搞定驱动问题
黑苹果配置不再难:Hackintool一站式解决方案让你15分钟搞定驱动问题 【免费下载链接】Hackintool The Swiss army knife of vanilla Hackintoshing 项目地址: https://gitcode.com/gh_mirrors/ha/Hackintool 还在为黑苹果的显卡驱动、音频输出和USB识别问题而…...
学Simulink——电池储能系统(BESS)双向DC-AC逆变器的恒压恒频(V/f)控制
目录 手把手教你学Simulink——电池储能系统(BESS)双向DC-AC逆变器的恒压恒频(V/f)控制 一、背景与挑战 1.1 什么是 V/f 控制?为什么 BESS 需要它? 1.2 核心痛点与设计目标 二、系统架构与核心控制推导 2.1 整体架构:电压源特性的“自主构建” 2.2 核心数学推导:…...
3分钟搞定网易云音乐NCM解密:ncmdump工具让你的音乐随处播放
3分钟搞定网易云音乐NCM解密:ncmdump工具让你的音乐随处播放 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 你是否曾为网易云音乐下载的歌曲只能在特定客户端播放而烦恼?当你想要在车载音响、智能音箱或其他…...
当AI开始检测自身缺陷:测试工具失控的风险与应对
在软件测试领域,AI正从辅助工具向核心角色转变。2026年的测试场景中,AI不仅能自动生成测试用例、自我修复失效选择器,还能以人眼精度完成视觉回归检测。这些能力让测试工程师从繁琐的重复劳动中解放出来,将精力聚焦于业务逻辑与边…...
Qt + OpenGL实战:手把手教你打造一个可交互的3D点云数据查看器(附CSV加载)
Qt OpenGL实战:打造工业级3D点云可视化工具全流程解析 在激光雷达测绘、三维重建和工业检测领域,点云数据的可视化一直是工程师面临的痛点。传统方案要么依赖昂贵的专业软件,要么需要从零造轮子实现OpenGL底层渲染。本文将展示如何基于Qt和…...
3步快速安装Android应用的终极指南:告别模拟器时代
3步快速安装Android应用的终极指南:告别模拟器时代 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾经想过在Windows电脑上直接运行Android应用&…...
AI——Dify高级RAG优化
高级RAG优化简介一、基础RAG的核心痛点二、全流程高级优化技术(一)索引构建阶段:高质量数据底座(二)检索阶段:精准召回与重排(三)检索后阶段:上下文压缩与提纯࿰…...
