使用canvas实现360水球波动
代码如下:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> <style> body { display: flex; flex-flow: column wrap; justify-content: center; align-items: center; } #circular { position: absolute; left: 500px; top: 400px; } #canvas_dom { position: absolute; left: 500px; top: 100px; } </style> </head> <body style="background-color: #0020cad6;"> <canvas id="circular" width="1000" height="1000">当前浏览器不支持canvas请升级!</canvas> <canvas id="canvas_dom" width="1000" height="1000"></canvas> </body> <script> canvas = document.getElementById("circular"); ctx = canvas.getContext("2d"); canvas.width = 800; oH = canvas.height = 800; // 线宽 lineWidth = 2; // 大半径 r = (canvas.width / 2); cR = r - 10 * lineWidth; ctx.beginPath(); ctx.lineWidth = lineWidth; // 水波动画初始参数 axisLength = 2 * r - 16 * lineWidth; // Sin 图形长度 unit = axisLength / 9; // 波浪宽 range = .3 // 浪幅 nowrange = range; xoffset = 8 * lineWidth; // 数据量 sp = 0; // 周期偏移量 nowdata = 0; waveupsp = 0.006; // 水波上涨速度 // 圆动画初始参数 arcStack = []; // 圆栈 bR = r - 8 * lineWidth; soffset = -(Math.PI / 2); // 圆动画起始位置 circleLock = true; // 起始动画锁 // 获取圆动画轨迹点集 for (var i = soffset; i < soffset + 2 * Math.PI; i += 1 / (8 * Math.PI)) { arcStack.push([r + bR * Math.cos(i), r + bR * Math.sin(i)]) } // 圆起始点 cStartPoint = arcStack.shift(); ctx.strokeStyle = "#1c86d1"; ctx.moveTo(cStartPoint[0], cStartPoint[1]); // 开始渲染 render(); var data = 0.5; setInterval(function(){ data = Math.round(Math.random()*10) /10; }, 2000); function drawSine() { ctx.beginPath(); ctx.save(); var Stack = []; // 记录起始点和终点坐标 for (var i = xoffset; i <= xoffset + axisLength; i += 20 / axisLength) { var x = sp + (xoffset + i) / unit; var y = Math.sin(x) * .2; var dx = i; var dy = 2 * cR * (1 - nowdata) + (r - cR) - (unit * y); ctx.lineTo(dx, dy); Stack.push([dx, dy]) } // 获取初始点和结束点 var startP = Stack[0] var endP = Stack[Stack.length - 1] ctx.lineTo(xoffset + axisLength, canvas.width); ctx.lineTo(xoffset, canvas.width); ctx.lineTo(startP[0], startP[1]); //水波的颜色 // 创建渐变 var grd=ctx.createLinearGradient(0,0,0,canvas.width); grd.addColorStop(0.3,"red"); grd.addColorStop(0.3,"#EEA2AD"); grd.addColorStop(0.5,"blue"); grd.addColorStop(0.7,"#D8BFD8"); grd.addColorStop(1,"white"); // 填充渐变 ctx.fillStyle=grd; ctx.fill(); ctx.restore(); } function drawText() { ctx.globalCompositeOperation = 'source-over'; var size = 0.2 * cR; ctx.font = 'bold ' + size + 'px Microsoft Yahei'; txt = (nowdata.toFixed(2) * 100).toFixed(0) + '%'; var fonty = r + size / 2; var fontx = r - size * 0.8; //字体颜色 ctx.fillStyle = "#00FA9A"; ctx.textAlign = 'center'; ctx.fillText(txt, r + 5, r + 5) } //最一层 function drawCircle() { ctx.beginPath(); ctx.lineWidth = 0; ctx.strokeStyle = '#00FFFF'; //不要直接 ctx.arc(r, r, cR + 7, 0, 2 * Math.PI); ctx.stroke(); ctx.restore(); } //第二层 function grayCircle() { ctx.beginPath(); //宽度 ctx.lineWidth = 12; //颜色 ctx.strokeStyle = '#7FFFAA'; ctx.arc(r, r, cR - 5, 0, 2 * Math.PI); ctx.stroke(); ctx.restore(); ctx.beginPath(); } //第二层进度圈 function orangeCircle() { ctx.beginPath(); //宽度 ctx.lineWidth = 2; ctx.strokeStyle = '#af1cd1'; //使用这个使圆环两端是圆弧形状 ctx.lineCap = 'round'; ctx.arc(r, r, cR - 5, - (Math.PI / 2) , (nowdata * 360) * (Math.PI / 180.0) - (Math.PI / 2)); ctx.stroke(); ctx.save() } //裁剪中间水圈 function clipCircle() { ctx.beginPath(); ctx.arc(r, r, cR - 15, 0, 2 * Math.PI, false); ctx.clip(); } //外员动态 function wytd(){ init_angle = 0; var small_x = Math.cos(init_angle)*80; var small_y = Math.sin(init_angle)*80; ctx.beginPath(); ctx.translate(small_x,0); ctx.arc(0,0,10,0,Math.PI*2); ctx.closePath(); ctx.fill(); ctx.restore(); init_angle = init_angle + Math.PI*2/360; if(init_angle >2 ){ init_angle = 0; } } //渲染canvas function render() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawCircle(); grayCircle(); //橘黄色进度圈// orangeCircle(); //裁剪中间水圈 clipCircle(); let aa = 10; if (data >= 0.85) { if (nowrange > range / 4) { var t = range * 0.01; nowrange -= t; } } else if (data <= 0.1) { if (nowrange < range * 1.5) { var t = range * 0.01; nowrange += t; } } else { if (nowrange <= range) { var t = range * 0.01; nowrange += t; } if (nowrange >= range) { var t = range * 0.01; nowrange -= t; } } if ((data - nowdata) > 0) { nowdata += waveupsp; } if ((data - nowdata) < 0) { nowdata -= waveupsp } sp += 0.07; drawSine(); // 写字 drawText(); requestAnimationFrame(render) } </script> <script type="text/javascript"> var canvas_dom = document.getElementById("canvas_dom"); var ctxfs = canvas_dom.getContext('2d'); var unit_angle = Math.PI*2/360; var init_angle = 0; function draw(){ //清除位置 ctxfs.clearRect(0,0,canvas_dom.width,canvas_dom.height); //第一个 ctxfs.save(); ctxfs.translate(500,300); ctxfs.fillStyle = "red"; ctxfs.beginPath(); ctxfs.arc(300,0,70,0,Math.PI*2,false); ctxfs.closePath(); ctxfs.fill(); var small_x = Math.cos(init_angle)*80; var small_y = Math.sin(init_angle)*80; ctxfs.beginPath(); //只需要修改后面参数 ctxfs.translate(small_x,20); //arc(移动左右位置,移动上下位置,大小,不需要修改,不需要修改) a ctxfs.arc(200,10,15,0,Math.PI*2); ctxfs.closePath(); ctxfs.fill(); ctxfs.restore(); init_angle = init_angle + unit_angle; //第二个 ctxfs.save(); ctxfs.translate(650,600); ctxfs.fillStyle = "red"; ctxfs.beginPath(); ctxfs.arc(300,0,70,0,Math.PI*2,false); ctxfs.closePath(); ctxfs.fill(); var small_x = Math.cos(init_angle)*80; var small_y = Math.sin(init_angle)*80; ctxfs.beginPath(); ctxfs.translate(small_x,0); ctxfs.arc(170,20,10,0,Math.PI*2); ctxfs.closePath(); ctxfs.fill(); ctxfs.restore(); //第三个 ctxfs.save(); ctxfs.translate(650,900); ctxfs.fillStyle = "red"; ctxfs.beginPath(); ctxfs.arc(300,0,50,0,Math.PI*2,false); ctxfs.closePath(); ctxfs.fill(); var small_x = Math.cos(init_angle)*80; var small_y = Math.sin(init_angle)*80; ctxfs.beginPath(); ctxfs.translate(small_x,0); ctxfs.arc(170,20,10,0,Math.PI*2); ctxfs.closePath(); ctxfs.fill(); ctxfs.restore(); //第四个 ctxfs.save(); ctxfs.translate(500,1100); ctxfs.fillStyle = "red"; ctxfs.beginPath(); ctxfs.arc(300,0,70,0,Math.PI*2,false); ctxfs.closePath(); ctxfs.fill(); var small_x = Math.cos(init_angle)*80; var small_y = Math.sin(init_angle)*80; ctxfs.beginPath(); ctxfs.translate(small_x,0); ctxfs.arc(170,20,10,0,Math.PI*2); ctxfs.closePath(); ctxfs.fill(); ctxfs.restore(); init_angle = init_angle + unit_angle; window.requestAnimationFrame(draw); } //自执行函数 (function(){ draw(); })(); </script> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
2018-08-16 csv