參考:
多邊形函數:https://www.cnblogs.com/anxia...
canvas畫波浪進度球:https://www.cnblogs.com/pagod...html
最近項目中須要一個六邊形的水波紋進度,在網上只找到了一個進度球的繪製方法,而後結合了一下多邊形的繪製方法,代碼以下
案例1:
代碼:canvas
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <style> body{ position: relative; width:100vw; height: 100vh; margin: 0; } canvas{ position: absolute; left: 50%; top: 50%; margin-left: -150px; margin-top: -150px; border: 1px dashed rgba(0,0,0,0.1) } </style> <body> <canvas id="c"></canvas> <input type="range" id="r" min="0" max="100" step="1"> </body> <script> var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); var range = document.getElementById('r'); //range控件信息 var rangeValue = range.value; var nowRange = 40; //用於作一個臨時的range //畫布屬性 var mW = canvas.width = 350; var mH = canvas.height = 350; var lineWidth = 1; //圓屬性 var r = mH / 2; //圓心 var cR = r - 32 * lineWidth; //圓半徑 //Sin 曲線屬性 var sX = 0; var axisLength = mW; //軸長 var waveWidth = 0.008 ; //波浪寬度,數越小越寬 var waveHeight = 6; //波浪高度,數越大越高 var speed = 0.09; //波浪速度,數越大速度越快 var xOffset = 0; //波浪x偏移量 ctx.lineWidth = lineWidth; //畫圈函數 var IsdrawCircled = false; var drawCircle = function(){ // 畫多邊形函數 function drawPath(x, y, n, r) { var i,ang; ang = Math.PI*2/n //旋轉的角度 ctx.save();//保存狀態 ctx.fillStyle ='rgba(255,0,0,.3)';//填充紅色,半透明 ctx.strokeStyle ='#000)';//填充綠色 ctx.lineWidth = 2;//設置線寬 ctx.translate(x, y);//原點移到x,y處,即要畫的多邊形中心 ctx.moveTo(0, -r);//據中心r距離處畫點 ctx.beginPath(); for(i = 0;i < n; i ++) { ctx.rotate(ang)//旋轉 ctx.lineTo(0, -r);//據中心r距離處連線 } ctx.closePath(); ctx.stroke(); ctx.fill(); ctx.restore();//返回原始狀態 } drawPath(r, r, 6, cR+1) drawPath(r, r, 6, cR) ctx.clip(); IsdrawCircled = true; } //畫sin 曲線函數 var drawSin = function(xOffset, color, waveHeight){ ctx.save(); var points=[]; //用於存放繪製Sin曲線的點 ctx.beginPath(); //在整個軸長上取點 for(var x = sX; x < sX + axisLength; x += 20 / axisLength){ //此處座標(x,y)的取點,依靠公式 「振幅高*sin(x*振幅寬 + 振幅偏移量)」 var y = Math.sin((-sX - x) * waveWidth + xOffset) * 0.8 + 0.1; var dY = mH * (1 - nowRange / 100 ); points.push([x, dY + y * waveHeight]); ctx.lineTo(x, dY + y * waveHeight); } //封閉路徑 ctx.lineTo(axisLength, mH); ctx.lineTo(sX, mH); ctx.lineTo(points[0][0],points[0][1]); ctx.fillStyle = color; ctx.fill(); ctx.restore(); }; var render = function(){ ctx.clearRect(0, 0, mW, mH); rangeValue = range.value; console.log(rangeValue); if(IsdrawCircled == false){ drawCircle(); } if(nowRange <= rangeValue){ var tmp = 1; nowRange += tmp; } if(nowRange > rangeValue){ var tmp = 1; nowRange -= tmp; } drawSin(xOffset+Math.PI*0.7, 'rgba(28, 134, 209, 0.5)', 18); drawSin(xOffset, '#1c86d1', 18); drawText(); xOffset += speed; requestAnimationFrame(render); } //寫百分比文本函數 var drawText = function(){ ctx.save(); var size = 0.4*cR; ctx.font = size + 'px Microsoft Yahei'; ctx.textAlign = 'center'; ctx.fillStyle = "rgba(06, 85, 128, 0.5)"; ctx.fillText(~~nowRange + '%', r, r + size / 2); ctx.restore(); }; render(); </script> </html>
效果圖函數
案例2:
代碼:this
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <style> body{ position: relative; width:100vw; height: 100vh; margin: 0; } canvas{ position: absolute; left: 50%; top: 50%; margin-left: -150px; margin-top: -150px; border: 1px dashed rgba(0,0,0,0.1) } </style> <body> <canvas id="c"></canvas> </body> <script> var canvas = document.getElementById('c'); var ctx = canvas.getContext('2d'); // 初始化參數 let oW = 236, oH = 267, lineWidth = 1, bOffset = 2, border = 3, //X軸偏移量 r, cR, axisLength, unit, // 浪寬 range = .3, // 浪高 nowrange = .3, sp = 0, // 週期偏移量 nowdata = 0, value = 0.5, // 百分比 waveupsp = 0.002; // 水波上漲速度 canvas.width = oW; canvas.height = oH; ctx.lineWidth = lineWidth; var triangleH = Math.ceil(oH/4); // 外六邊形 var arcStack = [ [oW/2, 0], [oW-bOffset, triangleH], [oW-bOffset,oH-triangleH], [oW/2, oH], [bOffset, oH-triangleH], [bOffset, triangleH] ]; var cStartPoint = arcStack.shift(); // 內六邊形 var arcStackInner = [ [oW/2, border], [oW-border, triangleH + border/2], [oW-border, oH-triangleH-border/2], [oW/2, oH-border], [border, oH - triangleH - border/2], [border,triangleH + border/2] ]; var cStartPointInner = arcStackInner.shift(); r = oW / 2; cR = oH/2 - border - lineWidth; ctx.beginPath(); axisLength = oW - 2*border; unit = axisLength / 20; ctx.beginPath(); renderBorder(); render(); function renderBorder() { ctx.beginPath(); ctx.strokeStyle = "#000000"; ctx.fillStyle = "#000000"; ctx.moveTo(cStartPoint[0], cStartPoint[1]); while (arcStack.length) { var temp = arcStack.shift(); this.ctx.lineTo(temp[0], temp[1]); ctx.stroke(); } ctx.lineTo(cStartPoint[0], cStartPoint[1]); ctx.stroke(); ctx.fill(); ctx.globalCompositeOperation = 'source-over'; ctx.beginPath(); ctx.fillStyle = '#fff' ctx.strokeStyle = '#fff'; ctx.moveTo(cStartPointInner[0], cStartPointInner[1]); while (arcStackInner.length) { var temp = arcStackInner.shift(); this.ctx.lineTo(temp[0], temp[1]); ctx.stroke(); } ctx.lineTo(cStartPointInner[0], cStartPointInner[1]); ctx.stroke(); ctx.fill(); ctx.restore(); ctx.clip(); ctx.save(); ctx.globalCompositeOperation = 'source-over'; } function render() { ctx.clearRect(0,0,oW,oH); if (value >= 0.85) { if (nowrange > range/4) { var t = range * 0.01; nowrange -= t; } } else if (value <= 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((value - nowdata) > 0) { nowdata += waveupsp; } if((value - nowdata) < 0){ nowdata -= waveupsp } sp += 0.07; if(value){ drawSine(); } requestAnimationFrame(render) } function drawSine() { ctx.beginPath(); ctx.save(); var Stack = []; for (let i = border; i <= border+axisLength; i+=20/axisLength) { var x = sp + (border + i) / unit; var y = Math.sin(x) * nowrange; var dx = i; var dy = 2*cR*(1-nowdata) + border - (unit * y); ctx.lineTo(dx, dy); Stack.push([dx,dy]); } var startP = Stack[0] ctx.lineTo(border + axisLength,oH + border); ctx.lineTo(border,oH+border); ctx.lineTo(startP[0], startP[1]) ctx.fillStyle = "#50bff7"; ctx.fill(); ctx.restore(); } function drawText() { ctx.save(); var size = 0.4*cR; ctx.font = size + 'px Microsoft Yahei'; ctx.textAlign = 'center'; ctx.fillStyle = "rgba(06, 85, 128, 0.5)"; let txt = (nowdata.toFixed(2)*100).toFixed(0) + '%'; ctx.fillText(txt, r, r + size / 2); ctx.restore(); } </script> </html>
效果圖spa