您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關canvas怎么實現環形進度條效果,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
這里就選canvas來簡單寫一下 先上代碼,然后在說一說需要注意的點:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canvas環形進度條</title> <style> body{ background-color:#000; text-align: center; } .canvas1{ margin-top: 100px; display: inline-block; background-color: #FFF; } </style> </head> <body> <canvas id="circle_process" class="canvas1"></canvas> <script> /* 需求:環形、一周分為10個片段,根據進度去走的一個狀態 技術選型:canvas (挑戰加熟悉) 思路: 01 首先中間的文字部分不用說,使用canvas的畫文字。 02 圓形是個規則圖形,那么為了避免畫不規則圖形,我們可以用圓和矩形來重疊出效果。 a. 大的灰色背景圓 b. 小一圈的白色背景圓 c. 以同心圓的圓心為圓心,小圓為半徑為半徑復制畫10個小的矩形 */ //初始化動畫變量 var requestAnimationFrame = window.requestAnimationFrame || window.msRequestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame; var cancelAnimationFrame = window.cancelAnimationFrame || window.msCancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelRequestAnimationFrame; //初始化當前進度數 var curPercentCount = 0; //獲取canvas對象,設置畫布大小 var oC = document.querySelector('#circle_process'); oC.width = 300; oC.height = 300; //獲取canvas執行上下文 var ctx = oC.getContext('2d'); //定義小矩形的個數 var miniRectCount = 10; //定義圓心位置 var cirCenter = { x:oC.width/2, y:oC.height/2 }; //定義小矩形的大小rectSize var rectSize = { width:0, height:0 }; //圓對象構造函數 function Circle(center,radius){ this.center = center; this.radius = radius; } //小矩形對象構造函數 function MiniRect(length,width){ this.length = length; this.width = width; } //角度轉換成弧度的函數 function d2a(angleInt){ return angleInt*Math.PI / 180; } //百分比轉換角度函數(這里減90因為arc0度是從右側開始的) function percentTurn(percentFloat){ return percentFloat * 360 / 100 - 90; } //畫當前百分比扇形的方法 function drawFanForPercent(percentFloat){ ctx.beginPath(); ctx.moveTo(cirCenter.x,cirCenter.y); ctx.lineTo(oC.width/2,(oC.height-baseCircle.radius*2)/2); ctx.arc(cirCenter.x,cirCenter.y,baseCircle.radius,d2a(-90),d2a(percentTurn(percentFloat))); ctx.fillStyle = 'aqua'; ctx.fill(); ctx.closePath(); } //畫圓的函數 function drawArc(center,radius,start,end,type,color){ start = start || 0; end = end || 360; ctx.beginPath(); ctx.arc(center.x,center.y,radius,d2a(start),d2a(end)); ctx.fillStyle = color; ctx.strokeStyle = color; if(!!type){ (type === 'fill') && ctx.fill(); (type === 'stroke') && ctx.stroke(); } ctx.closePath(); } //畫文字的函數 function drawPercentText(text,percentInt){ ctx.beginPath(); ctx.fillStyle = 'aqua'; ctx.font="italic small-caps bold 40px Calibri"; ctx.textAlign = 'center'; ctx.fillText(text,cirCenter.x,cirCenter.y-18,100); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = 'aqua'; ctx.font="italic small-caps bold 60px Calibri"; ctx.textAlign = 'center'; ctx.fillText(percentInt+'%',cirCenter.x,cirCenter.y+40,100); ctx.closePath(); } //畫小方塊的方法 function drawMiniRect(startPoint,width,height,axisPoint,rotateAngle){ /* ctx.beginPath(); //平移,畫出第一個 ctx.save(); ctx.translate(startPoint.x,startPoint.y); ctx.fillStyle = '#FFF'; ctx.fillRect(0,0,rectSize.width,rectSize.height); ctx.restore(); ctx.closePath(); //這種先平移畫出在旋轉的思路是錯的,畫之后就不能轉了 ctx.save(); ctx.translate(axisPoint.x,axisPoint.y); ctx.rotate(rotateAngle); ctx.restore(); */ ctx.save(); ctx.translate(axisPoint.x,axisPoint.y); /*畫布平移到圓的中心*/ ctx.rotate(d2a(rotateAngle)); /*旋轉*/ /*畫*/ ctx.beginPath(); ctx.fillStyle = '#FFF'; ctx.fillRect(startPoint.x,startPoint.y,rectSize.width,rectSize.height); ctx.closePath(); ctx.restore(); } //畫整體 function draw(curPercent){ //底部灰色圓 drawArc(baseCircle.center,baseCircle.radius,null,null,'fill','#CCC'); //進度扇形 drawFanForPercent(curPercent); //內部白色遮擋圓 drawArc(innerCircle.center,innerCircle.radius,null,null,'fill','#FFF'); //畫文字 drawPercentText('當前進度',curPercent); //十個小的矩形 for(var i=0; i<miniRectCount; i++){ drawMiniRect(startPoint,rectSize.width,rectSize.height,cirCenter,i*360/miniRectCount); } } //實例化底圓和內圓 var baseCircle = new Circle(cirCenter,130); var innerCircle = new Circle(cirCenter,100); //設置rectSize數值 rectSize.width = 15; rectSize.height = baseCircle.radius - innerCircle.radius + 5; //設置第一個小矩形的起始點 (這里有誤差) // var startPoint = { // x: oC.width /2 - 7.5, // y: (oC.height - baseCircle.radius*2) / 2 // }; //由于平移到中心點之后畫的位置是在畫布外的,所以重新定義 var startPoint = { x:-7.5, y:-baseCircle.radius - 2 }; //這里開定時去顯示當前是百分之幾的進度 var raf = null; var percent = 0; function actProcess(percentFloat){ percentFloat = percentFloat || 100; percent = Math.round(percentFloat); console.log(percent); curPercentCount++; raf = requestAnimationFrame(function(){ actProcess(percentFloat); }); draw(curPercentCount); if(curPercentCount >= percent){ cancelAnimationFrame(raf); return; } } actProcess(50); // cancelAnimationFrame(raf); //這里沒搞懂為什么percent會加 ? //解: requestAnimationFrame中方法還是需要有參數,這里就用匿名函數回調的執行體去指定。 /* //setInterval的方式 function actProcess(percentFloat){ if(curPercentCount >= percentFloat){ clearInterval(timer); return; } curPercentCount++; draw(curPercentCount); } clearInterval(timer); var timer = setInterval(function(){ actProcess(50); },16.7); */ //直接畫弧形的測試: //drawArc(innerCircle.center,innerCircle.radius,0,260,'fill','red'); /* 用到的技術點: 01 canvas平移 02 canvas畫布狀態保存于恢復 03 canvas旋轉 04 canvas clearRect配合動畫requestAnimationFrame 05 canvas寫文字 */ </script> </body> </html>
接下來說一些注意點和我寫的過程中碰到的疑問:
疑問:
01 整體代碼沒有封裝成一個組件,感興趣的同學可以封裝一下。 我這有時間也會封裝。
02 畫文字的時候只能單獨畫一行文字么? 怎樣進行換行?
03 canvas怎樣處理響應式?
注意點:
01 畫布平移之后,畫布上的點也會被平移,所以我在定義第一個小矩形的起始點的時候才會重新定義一個負值。
02 直接畫弧形來控制進度不準確,因為arc會自動closePath(),最終形成這樣的一個效果。
03 默認圓的0度起始位置是從3點鐘方向開始的(見上圖),那么想從12點鐘位置開始走進度,需要減去90度的角度。
04 requestAnimationFrame的回調函數在有參數的情況下還是需要傳參數的,需要借助匿名函數回調,在執行體里面去執行想要loop的函數內容(可傳參數)。否者會出現注釋中寫道的pecent不規則增加的問題。
先就這樣,之后可能會結合一個上傳圖片的小功能嘗試把它封裝成一個組件。
關于“canvas怎么實現環形進度條效果”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。