当前位置: 首页 > 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;添加数据库和表 …...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...