先上源码:
<!DOCTYPE html><html lang=”en”>
<head> <meta charset=”UTF-8″> <meta http-equiv=”X-UA-Compatible” content=”IE=edge”> <meta name=”viewport” content=”width=device-width, initial-scale=1.0″> <title>Document</title> <style> .box { position: relative; } /* 绘制箭头 */ .arrow { position: absolute; top: 165px; left: 200px; width: 4px; height: 40px; background-color: #000; cursor: pointer; } .arrow::after{ content: “”; display: block; position: absolute; top: -5px; left: -3px; width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 10px solid #000; } </style></head>
<body> <div class=”box”> <canvas id=”canvas”></canvas> <div class=”arrow”></div> </div> <script> /** @type {HTMLCanvasElement} */ let canvas = document.getElementById(“canvas”), arrow = document.getElementsByClassName(“arrow”)[0], ctx = canvas.getContext(‘2d’), width = 400,//canvas 宽度 height = 400,//canvas 高度 r = 200,//转盘宽度 rtext = 140,//文本围成的圆半径 startRadian = 0,//圆弧开始弧度数 endRadian = 0,//圆弧结束弧度数 prize = [“10元话费”, “20元话费”, “30元话费”, “40元话费”, “50元话费”, “60元话费”],//奖品 i=1,//抽奖次数 flag = false,//正在抽奖中 angle=360/prize.length;//单个圆弧的角度数
canvas.width = width; canvas.height = height;
// 偏移画板,使用中心点作为(0,0)点 ctx.translate(width / 2, height / 2);
// 绘制转盘 prize.forEach((item, index) => { startRadian = Math.PI * 2 / prize.length * index; endRadian = Math.PI * 2 / prize.length * index + Math.PI * 2 / prize.length; turntable(item, index); }) // 绘制一个圆弧 function turntable(item, index) { ctx.save(); ctx.beginPath(); ctx.moveTo(0, 0); ctx.fillStyle = index % 2 == 0 ? “rgba(0,0,0,0.2)” : “rgba(0,0,0,0.1)”; ctx.arc(0, 0, r, startRadian, endRadian) ctx.fill(); ctx.closePath(); ctx.restore();
ctx.save(); ctx.beginPath(); ctx.font = “14px 微软雅黑”;
// 计算出文本的初始偏移坐标 let x1 = Math.cos(Math.PI / 180 * (angle/2 + index * angle)) * rtext; let y1 = Math.sin(Math.PI / 180 * (angle/2 + index * angle)) * rtext;
// 处理居中问题,计算出初始坐标基础的偏移量 let x2 = Math.sin(Math.PI / 180 * (angle/2 + index * angle)) * ctx.measureText(item).width / 2; let y2 = Math.cos(Math.PI / 180 * (angle/2 + index * angle)) * ctx.measureText(item).width / 2;
// 使用最终的坐标偏移 ctx.translate(x1 + x2, y1 – y2)
// 对偏移后的坐标进行旋转 ctx.rotate(Math.PI / 180 * (90+angle/2 + index * angle));
ctx.fillText(item, 0, 0); ctx.closePath(); ctx.restore(); } // 点击抽奖 arrow.addEventListener(“click”, function () { if(flag) return; flag = true; let x = Math.floor(Math.random() *prize.length), deg = 3600*i + (180+angle – x * angle+(prize.length%4==0?angle/2:0)); canvas.style.transition = “all 6s cubic-bezier(0, 0.98,0.99, 1)” canvas.style.transform = “rotate(” + deg + “deg)”; i++; setTimeout(() => { console.log(x+1) flag = false; }, 6000); }) </script></body>
</html>
思路:
1、首先根据设置的奖品数量绘制转盘
2、使用数学中的三角函数计算出文本的偏移量以及旋转的角度
3、添加dom点击事件
4、使用css的transition 和transform属性设置转盘动画
5、计算出奖品的旋转角度
以上就是canvas转盘抽奖互动小游戏大概的思路,欢迎讨论~
1 条回复
[…] 网上找的很多都是基于三角函数的解决方案,我也手码了一份,具体可以参考:三角函数方案:canvas转盘抽奖互动小游戏源码,附带效果 […]