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

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
  • 🚀六、总结


🚀一、引言

大转盘抽奖是一种常见的游戏方式,用户可以通过点击按钮让指针开始旋转,在经过一段时间后指针会停下来,显示用户中奖的奖项。本文将用JavascriptHTML实现一个简单的大转盘抽奖功能。详细介绍实现思路和代码。

⭐⭐文末附完整代码⭐⭐

🚀二、开发思路

本文将使用JavaScriptHTML来实现一个简单的大转盘抽奖功能。具体步骤如下:

  1. 创建HTML结构:使用HTML创建一个大转盘容器,包括转盘、指针和抽奖按钮。
  2. 使用CSS样式:使用CSS样式来美化大转盘的外观,包括颜色、字体等。
  3. 使用JavaScript编写抽奖逻辑:根据配置的奖项和概率,计算中奖结果,并设置指针的旋转动画效果。
  4. 绑定点击事件:为抽奖按钮绑定点击事件,点击按钮后开始抽奖逻辑。
  5. 弹出中奖内容:抽奖结束后,使用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秒后停止并弹出中奖内容。

  1. macbook 14pro,中奖概率10%。
  2. iPhone13,中奖概率30%。
  3. xiaomi手机,中奖概率20%。
  4. 100元商城优惠券,中奖概率20%。
  5. 感谢参与,中奖概率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();

🚀六、总结

本文使用JavaScriptHTML实现了一个的大转盘抽奖功能。通过配置奖项和概率,用户可以根据自己的需要来设置抽奖的规则。点击抽奖按钮后,指针开始旋转,经过5秒后停止,并弹出中奖内容。

以上就是本文的具体思路和代码实现,通过这个示例,你可以了解到如何使用JavaScriptHTML来实现大转盘抽奖功能。希望对你有所帮助!实际的应用中,可以基于上面的内容修改。

在这里插入图片描述

今天的内容就到这里,我们下次见。

相关文章:

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

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f3c6;本文已…...

yay无法更新问题解决

背景 更新yay后&#xff0c;yay安装软件捞出问题&#xff0c;查的github上的都不靠谱。因此需要把yay的版本固定下&#xff0c;正常的11版本是可用的 解决方案 sudo pacman -S --needed git base-devel git clone https://aur.archlinux.org/yay.git cd yay makepkg -si # 注…...

C语言 — 动态内存管理(动态内存函数)

前言 本期分为三篇介绍动态内存管理相关内容&#xff0c;关注博主了解更多 博主博客链接&#xff1a;https://blog.csdn.net/m0_74014525 本期介绍动态内存函数&#xff0c;函数如何使用、函数格式、在使用在所需要的注意点及C/C程序的内存开辟区域 系列文章 第一篇&#xff…...

Visual ChatGPT:Microsoft ChatGPT 和 VFM 相结合

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是Visual ChatGPT&#xff1f; Visual ChatGPT 是一个包含 Visual Foundation 模型 &#xff08;VFM&#xff09; 的系统&#xff0c;可帮助 ChatGPT 更好地理解、生成和编辑视觉信息。VFM 能够指…...

基于java理发店预约系统微信小程序设计与实现

摘要 多姿多彩的世界带来了美好的生活&#xff0c;行业的发展也是形形色色的离不开技术的发展。作为时代进步的发展方面&#xff0c;信息技术至始至终都是成就行业发展的重要秘密。不论何种行业&#xff0c;大到国家、企业&#xff0c;小到团体、个人都在多方位的结合信息化技术…...

【软件测试】大厂测工都是这样学习的,你get到了吗?

有不少的软件测试工程师站在“十字路口”迷茫、无助&#xff0c;找不到自己的方向。一切的迷茫都是因为想得太多而做的太少&#xff01;每位软件测试行业从业者都能意识到目前自己面临的窘境&#xff0c;但能及时作出改变&#xff0c;顺应时代变化的人还是太少。多数人明明“泰…...

如何使用ONLYOFFICE+ffmpeg来给视频文件打马赛克

如何使用ONLYOFFICEffmpeg来给视频文件打马赛克 我这里之前写过很多关于ONLYOFFICE使用、安装的系列图文&#xff0c;也写过很多关于ffmpeg使用的图文&#xff0c;那么这次继续&#xff0c;把这两个开源软件放在一起&#xff0c;能碰撞出什么火花般的功能来。 这就是给视频文…...

003-依赖注入、属性赋值源码分析

目录 引入作用代码分析InstantiationAwareBeanPostProcessor#postProcessProperties()AutowiredAnnotationBeanPostProcessor查找注入点元数据给注入点注入属性 引入 之前我们了解到BeanDefinition到Bean&#xff0c;经历了 实例化属性赋值初始化 3个步骤现在详细分析下属性赋…...

Elasticsearch 商业启示

上月的“红帽事件”&#xff0c;说明开源软件的“客服模式”行不通&#xff0c;那么&#xff0c;开源软件如何赚钱呢&#xff1f;既不能卖软件&#xff0c;又不能卖支持服务&#xff0c;该怎么办呢&#xff1f;我现在的看法是&#xff0c;只剩下一种模式是可行的&#xff0c;开…...

C++/Qt 读写文件

之前写过两篇跟文件操作相关的博客&#xff0c;有兴趣也可以看一下&#xff1a; C语言读写文件 Qt关于文件路径的处理 先讲一些关于基础文本文件和二进制文件的读写操作&#xff0c;后续将会整理C/Qt关于ini、xml、json、xlsx相关文件的读写操作。 C 相比于C语言使用FILE文…...

linux服务器之-nethogs命令

文章目录 NetHogs 工具安装安装依赖包安装epel源安装Nethogs 使用 NetHogs 工具 NetHogs是一个小型的net top工具&#xff0c;不像大多数工具那样拖慢每个协议或者是每个子网的速度而是依照进程进行带宽分组。 安装 安装依赖包 yum install libpcap libpcap-devel epel-rel…...

《每天5分钟玩转kubernetes》读书笔记

笔记 概念 Pod是脆弱的&#xff0c;但应用是健壮的。 kubelet运行在Cluster所有节点上&#xff0c;负责启动Pod和容器。kubeadm用于初始化Cluster。kubectl是k8s命令行工具。通过kubectl可以部署和管理应用&#xff0c;查看各种资源&#xff0c;创建、删除和更新各种组件。 …...

【RabbitMQ】golang客户端教程4——路由(使用direct交换器)

路由 在上一教程中&#xff0c;我们构建了一个简单的日志记录系统。我们能够向许多接收者广播日志消息。 在本教程中&#xff0c;我们将向它添加一个特性-我们将使它能够只订阅消息的一个子集。例如&#xff0c;我们将只能将关键错误消息定向到日志文件&#xff08;以节省磁盘…...

Shell脚本学习-for循环结构2

案例&#xff1a;通过脚本实现仅sshd、rsyslog、crond、network、sysstat服务在开机时自启动。 Linux系统在开机的服务通常工作在文本模式3级别&#xff0c;因此只需要查找3级别以上的开启的服务即可。查看命令&#xff1a; chkconfig --list |grep 3:on [rootvm1 ~]# chkco…...

vue 老项目 npm install 报错Python,c++等相关错误

​​​ 老项目npm install 下载依赖包报错 解决方法&#xff1a; //下载python 1、 npm install --global --production windows-build-tools//配置环境 &#xff1a; 也可暂时不用配置,能用就不用配置&#xff08;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的基础之上&#xff0c;容纳进去了面向对象编程思想…...

idea打开传统eclipse项目

打开传统web项目 1.打开后选择项目文件 2.选择项目结构 3.设置jdk版本 4.导入当前项目模块 5.选择eclipse 6. 设置保存目录 7.右键模块&#xff0c;添加spring和web文件 8. 设置web目录之类的&#xff0c;并且创建打包工具 9.如果有本地lib&#xff0c;添加为库 最后点击应用&…...

全国各城市-财政收入-一般预算收入-各项税收-个人所得税(1999-2020年)

个人所得税是一项反映国家财政状况和个人经济水平的重要数据。通过对全国各城市个人所得税数据的研究&#xff0c;可以提供研究者参考的有益信息。首先&#xff0c;个人所得税数据反映了不同城市居民的收入水平。通过对不同城市的个人所得税数据进行比较&#xff0c;可以了解不…...

【动态网页抓取】 :用Python抓取所有内容的指南

一、说明 您在抓取动态网页内容时是否得到了糟糕的结果&#xff1f;不仅仅是你。对于标准抓取工具来说&#xff0c;爬网动态数据是一项具有挑战性的任务&#xff08;至少可以说&#xff09;。这是因为当发出HTTP请求时&#xff0c;响应程序的某些部分JavaScript在后台运行&…...

Spring Boot数据访问基础知识与JDBC简单实现

目录 Spring Boot数据访问基础知识 Spring Data ORM JDBC JPA JDBC简单实现 步骤1&#xff1a;新建Maven项目&#xff0c;添加依赖 步骤2&#xff1a;配置数据源—让程序可以访问到 步骤3&#xff1a;配置数据源—让IDEA可以访问到 步骤4&#xff1a;添加数据库和表 …...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)

Name&#xff1a;3ddown Serial&#xff1a;FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名&#xff1a;Axure 序列号&#xff1a;8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...

五、jmeter脚本参数化

目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...