自己通过canvas+vue(vue不是必备的可以)实现的一个抽奖转盘,重点在实现逻辑,所以样式丑绝。
基本效果图,中间指针可以替换为图片

数据格式

转盘的分块由传入的数组长度确定,分为4,6,8块还是能看的

 {id: 1, // 奖品标识,可按需设置content: "谢谢参与", // 奖品文本prize: "111", //奖品内容probability: 0.75, // 中奖概率,也可以不设,由后台决定是否中奖及中了什么奖img: "https://img.stringon.com/dd4cffa524bf46f790520a46fefd1726-S375",// 奖品图片,按需设置},{id: 2,content: "现金红包2元",prize: "222",probability: 0.05,img: "https://img.stringon.com/c0f57be115e541fd90b8df5ef163110b-S375",},{id: 3,content: "现金红包10元",prize: "333",probability: 0.02,img: "https://img.stringon.com/c0f57be115e541fd90b8df5ef163110b-S375",},{id: 4,content: "现金红包3元",prize: "444",probability: 0.04,img: "https://img.stringon.com/c0f57be115e541fd90b8df5ef163110b-S375",},

html部分

第一个canvas绘制大转盘

第二个canvas绘制中间转盘,可替换为图片(用drawImage绘制)

<div class="turn-box"><canvas id="chart" ref="turnBox" height="400" width="600">你的浏览器不支持HTML5 canvas</canvas><canvas id="centerChart" ref="centerChart" height="400" width="600">你的浏览器不支持HTML5 canvas</canvas></div>

css部分

css部分比较简单,主要用来定位两个canvas之间的位置

.turn-box {position: relative;
}
canvas {position: absolute;left: 0;right: 0;margin: auto;top: 0;
}
#centerChart {top: 50px;
}

js部分

重点的总是留在最后,下面是实现代码,注释我会尽量写的清楚一点

// data初始化
data(){return{canvas: null,ctx: null,width: 262, // 宽height: 262, // 高count: 12,//抽奖次数,也是从后台请求running: null,//是否正在抽奖turnInfo:[] //奖品信息,一般从后台请求}
},
computed: {//为了方便比较,这里是中奖区域,如果由后台返回中奖信息,那这里就是不需要的randList() {let start = 0;return this.turnInfo.map((item) => {start = item.probability + start;return Number(start.toFixed(2));});},},
mounted() {// 获得canvas上下文this.canvas = document.getElementById("chart");if (this.canvas && this.canvas.getContext) {this.ctx = this.canvas.getContext("2d");}this.drawCharts(); //绘制const that = this;// 点击抽奖this.canvas.onclick = async function () {if (that.count === 0) return; //没有抽奖次数处理逻辑if (that.running) return; //正在抽奖中处理逻辑const rand = that.getPrize();//获取中奖信息that.$refs.turnBox.style.transform = "unset";that.$refs.turnBox.style.transition = "all 0s";//先将之前旋转状态重置await setTimeout(() => {let deg = 1800 + 360 - (360 / that.turnInfo.length) * rand;//计算旋转角度,1800(360*5)为多旋转的角度that.$refs.turnBox.style.transform = `rotate(${deg}deg)`;that.$refs.turnBox.style.transition = "all 3s ease-in-out";//开始旋转});console.log(that.turnInfo[rand].content);//输出中奖信息that.running = setTimeout(() => {clearTimeout(that.running);that.running = null;正在抽奖状态重置that.count -= 1;//中奖次数减一}, 3000);//延迟时间为转盘旋转动画时间};},
methods:{// 图表初始化initChart() {//   这里是对高清屏幕的处理,// 方法:先将canvas的width 和height设置成本来的两倍//     然后将style.height 和 style.width设置成本来的宽高//     这样相当于把两倍的东西缩放到原来的 1/2,这样在高清屏幕上 一个像素的位置就可以有两个像素的值//     这样需要注意的是所有的宽高间距,文字大小等都得设置成原来的两倍才可以。this.canvas.width = this.width * 2;this.canvas.height = this.height * 2;this.canvas.style.height = `${this.height}px`;this.canvas.style.width = `${this.width}px`;this.ctx.translate(0.5, 0.5); // 当只绘制1像素的线的时候,坐标点需要偏移,这样才能画出1像素实线},//绘制大转盘drawTurnBox() {let num = this.turnInfo.length;this.ctx.font = "bold 18px Microsoft YaHei";for (let i = 0; i < num; i++) {//根据奖品参数 绘制扇形填充颜色,按需设置// ctx.fillStyle = this.turnInfo.colors[i];//开始绘制扇形this.ctx.save();this.ctx.beginPath();this.ctx.translate(this.width, this.width);// // 从(0, 0)坐标开始定义一条新的子路径this.ctx.moveTo(0, 0);this.ctx.rotate(((360 / num) * (i + 1) * Math.PI) / 180);//arc(x,y,r,起始角,结束角,绘制方向) 方法创建弧/曲线(用于创建圆或部分圆)this.ctx.arc(0, 0, this.width, 0, (2 * Math.PI) / num, false);this.ctx.arc(0, 0, this.width / 2 - 50, (2 * Math.PI) / num, 0, true);if ((i + 1) % 2 == 0) {this.ctx.fillStyle = "#ffb820";} else {this.ctx.fillStyle = "#ffcb3f";}// this.ctx.lineWidth = 0.5;this.ctx.strokeStyle = "transparent";this.ctx.stroke();this.ctx.fill();this.ctx.restore();}},// 绘制文本drawText() {let num = this.turnInfo.length;this.ctx.font = "24px Arial";let arc = Math.PI / (num / 2);for (let i = 0; i < num; i++) {let angle = 0 + i * arc;this.ctx.save();//奖品默认字体颜色// this.ctx.fillStyle = "#fff";let text = this.turnInfo[i].content;this.ctx.translate(this.width + Math.cos(angle + arc / 2) * (this.width - 40),this.width + Math.sin(angle + arc / 2) * (this.width - 40));this.ctx.rotate(angle + arc / 2 + Math.PI / 2);//由于设计的转盘色块是交错的,所以这样可以实现相邻奖品区域字体颜色不同// if (i % 2 == 0) {//   this.ctx.fillStyle = "#fff";// }//将字体绘制在对应坐标this.ctx.fillText(text, -this.ctx.measureText(text).width / 2, 20);//设置字体// this.ctx.font = " 14px Microsoft YaHei";//把当前画布返回(插入)到上一个save()状态之前this.ctx.restore();//绘制奖品图片if (this.turnInfo[i].img) {let img = new Image();img.src = this.turnInfo[i].img;img.onload=()=>{this.ctx.save();this.ctx.translate(this.width + Math.cos(angle + arc / 2) * this.width,this.width + Math.sin(angle + arc / 2) * this.width);this.ctx.rotate(angle + arc / 2);this.ctx.drawImage(img, -this.width / 2 + 10, -50, 42, 94);this.ctx.restore();}}}},// 绘制中间圆盘drawCenter() {const canvas = document.getElementById("centerChart");canvas.style.top = `${63}px`;// 位置自己定啦let ctx = null;if (canvas && canvas.getContext) {ctx = canvas.getContext("2d");}let arc = Math.PI / (this.turnInfo.length / 2);canvas.width = this.width;canvas.height = this.height;canvas.style.height = `${this.height / 2}px`;canvas.style.width = `${this.width / 2}px`;ctx.translate(0.5, 0.5);ctx.save();ctx.fillStyle = "#ffcb3f";ctx.beginPath();ctx.translate(this.width / 2, this.width / 2);ctx.rotate(arc / this.turnInfo.length + Math.PI / 180);//这一部分可以通过drawImage直接绘制成图片,保留中心点设置与旋转角度即可,其他的都随意ctx.moveTo(0, 40);ctx.lineTo(this.width / 2, 40); //绘制指针ctx.arc(0, 0, this.width / 2 - 40, 2 * Math.PI, 0, true);//绘制圆ctx.lineWidth = 1;ctx.strokeStyle = "rgba(0,0,0,0.45)";ctx.stroke();ctx.fill();ctx.restore();},// 开始绘制drawCharts() {this.drawCenter(); //绘制中心圆this.initChart(); // 图表初始化this.drawTurnBox(); // 绘制转盘this.drawText(); // 绘制文字},//获取中将信息,中奖信息由后台返回会比较安全,这里只需要返回中奖的索引就可以getPrize() {let rand = Number(Math.random().toFixed(2));//中奖随机数let prizeIndex = -1;//中奖索引let index = 0;while (prizeIndex === -1 && index < this.randList.length) {prizeIndex = this.randList[index] >= rand ? index : -1;index++;}return prizeIndex;},
}

写在最后

以上就是我实现抽奖大转盘的全部代码,写得比较急,代码粗糙,样式我自己都不忍直视,如果我记得并且有时间的话,我还会进行优化的。
项目地址:抽奖转盘demo
ps:推荐一下我自己写的二维码生成器,有输入字符生成和上传.txt文件生成,主要是希望有人使用后给我提出一些修改意见:qrcode-generator

vue幸运抽奖大转盘的丑绝实现相关推荐

  1. vue 实现抽奖大转盘

    实际解决需求,前端只是负责页面转动,在用户点击时,请求中奖接口,同同时通过设置css属性,让转盘转动起来,当转盘转动结束后,根据请求后端接口回来的中奖信息,设置转盘的转动位置,然后进行弹窗显示中奖信息 ...

  2. vue实现抽奖大转盘

    1. 实现原理 实际解决用户需求:当用户点击抽奖时,会请求接口获取中奖的奖品信息,前端根据中奖编号进行修改css样式,让转盘旋转,调整角度对应后端返回的奖品.如果抽奖有多次机会的话,每次需要抽奖结束后 ...

  3. 用c语言写抽奖大转盘,iOS抽奖大转盘的二种实现方法

    有个朋友需要写个抽奖大转盘的功能,就让我帮忙写了下.我用了2种方法实现了效果,在这里和大家一起分享下. 一.一键转动大转盘 我一开始拿到手的是一堆的图片,然后自己花了点时间,搭建出美工要求的UI,接下 ...

  4. css3抽奖转盘,从零制作CSS3抽奖大转盘

    今天的任务是做一个纯CSS3的还算比较漂亮的抽奖大转盘,也就是下图效果. 我只说思路和重要的CSS3代码. Paste_Image.png 外盘 外盘是指有彩灯的深橙色圆环,以及圆环的外边线. 外盘设 ...

  5. javaScript实现抽奖大转盘(一)

    今天试了试自己写个抽奖大转盘. 先是借了两张别人的图片: 下面是布局部分: <div class="round"><div class="box&quo ...

  6. 微信小程序独家秘笈之抽奖大转盘

    代码地址如下: http://www.demodashi.com/demo/14209.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.c ...

  7. 抽奖大转盘-React-移动端

    抽奖大转盘-React-移动端 react安装 修改项目结构 配置路由 删除一些不必要的文件 大转盘 整理代码结构和一些静态资源 书写静态页面 移动端px-rem转换 静态页面 静态页面样式 抽奖大转 ...

  8. 优秀课程案例:使用Scratch制作一个抽奖大转盘方法二!

    点击上面微信号关注我关注我哟每天坚持早上9:00左右推送文章,争取做到日更,喜欢的可以设置星标,并分享点赞我们的文章,非常感谢大家的支持,您的点击的在看就是我们的动力! 昨天我们分享了一个抽奖大转盘: ...

  9. Redis 抽奖大转盘的实战示例

    本文主要介绍了Redis 抽奖大转盘的实战示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下.编程学习资料点击领取 目录 1. 项目介绍 2. 项目演示 3. 表结 ...

最新文章

  1. 如何在Mysql的Docker容器启动时初始化数据库
  2. python中文意思k-对python中的*args与**kwgs的含义与作用详解
  3. LeetCode Number of Islands(flood fill)
  4. simplexml和xpath
  5. Linux日常运维(rsync通过服务连接,linux日志,screen)
  6. 宏定义Define的一些用法
  7. [译] Facebook杯2013年编程挑战赛——预选赛题目及答案
  8. 当动物保护用上AI……
  9. Stopping filebeat
  10. js省市二级联动;)
  11. CSS的样式合并与模块化
  12. BZOJ3680 吊打XXX
  13. it营Typescript学习笔记02(基础完结)模块,命名空间,装饰器
  14. 0.88mm液晶拼接屏在会议显示中的优势分析
  15. Singularity 快速上手, 带你飞
  16. 地铁WIFI可以用来挣钱,可挣钱却注定很难
  17. c语言发票的编码,增值税普通发票(折叠票)的发票代码有几位?
  18. 电商平台-安全设计与架构
  19. JavaScript - 基础+WebAPI(笔记)
  20. 全国计算机应用技术证书考试文字处理,全国计算机应用技术证书考试文字处理考试大纲2015年版考试.DOC...

热门文章

  1. thinkpadE485做java_ThinkPad E485笔记本安装win10系统操作教程
  2. cad2014卡顿的解决方法_cad卡顿完美解决(AutoCAD运行卡顿怎么办)
  3. kubernetes之Cronjob应用和踩坑
  4. Arduino制作天猫精灵朋友天狗精灵-LD3320语音模块
  5. 2021大年三十牛气冲天祝福语
  6. Illustrator 教程:如何在 Illustrator 中添加效果?
  7. 城市防汛应急管理智慧 Web GIS 可视化平台
  8. 7的整除特征 三位一截_数学:被7整除的数的特征
  9. Photoshop制作具有梦幻效果的宣传海报
  10. 网购秒杀系统架构设计分析