詳解JavaScript+Canvas繪制環(huán)形進度條
效果圖

思考
移動端的場景里經常會出現環(huán)形進度條的功能,在實現這個功能前,我預想的解決方案大致有: echarts、antv、canvas、svg
前面兩種第三方提供的解決方案當然是簡單,拿到案例修整一下即可,但是需要下載依賴,而且代碼量不小。有沒有不需要依賴第三方包,采用原生的寫法,獨立封裝成一個組件,降低耦合,而且性能優(yōu)越?
當然,那就主要介紹canvas的使用
實現思路
可以展示整個圓、半圓以及任意角度弧形(左右對稱)的進度條。整體思路如下:
1.先確定展示的形狀,是整個圓、半圓還是一般的弧形
2.把確定好形狀的圓弧均分100等份,計算出每一份所占的弧度
3.灰色圓弧占100份,紅色圓弧最終占的份數由參數確定
4.設置setInterval定時器,重復執(zhí)行畫圖操作
- 清空畫布
- 先畫灰色的圓弧,占100份
- 再畫紅色的圓?。杭t色圓弧的份數從0開始,每次加1
- 畫紅色圓弧末端的紅色圓:難點在于根據角度確定紅色圓的圓心,這里面涉及到三角函數,在草稿紙上畫個圖就大致明白了
- 當紅色圓弧的份數達到指定值(傳的參數)的時候,清除定時器
具體代碼實現
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Canvas</title>
</head>
<body>
<canvas id="canvas" width="300" height="300"></canvas>
<script>
draw(66);
/**
* [順時針方向畫圖,起始點在左側]
* @param {[number]} percent [所占的進度百分比,比如66%,則傳66即可,0 <= percent <= 100]
* @param {[number]} sR [圓弧起始角度,可不傳,默認是π/2,Math.PI/2 <= sR < 3/2 * Math.PI]
*/
function draw(percent, sR) {
if (percent < 0 || percent > 100) {
return;
}
if (sR < Math.PI/2 || sR >= 3/2 * Math.PI) {
return;
}
var canvas = document.querySelector('#canvas'),
cxt = canvas.getContext('2d'),
cWidth = canvas.width,
cHeight = canvas.height,
baseColor = '#e1e1e1',
coverColor = '#fe4d43',
PI = Math.PI,
sR = sR || 1/2 * PI; // 默認圓弧的起始點弧度為π/2
var finalRadian = sR + ((PI + (PI - sR) * 2) * percent / 100); // 紅圈的終點弧度
var step = (PI + (PI - sR) * 2)/100; // 一個1%對應的弧度大小
var text = 0; // 顯示的數字
var timer = setInterval(function() {
cxt.clearRect(0, 0, cWidth, cHeight);
var endRadian = sR + text * step;
// 畫灰色圓弧
drawCanvas(cWidth/2, cHeight/2, 80, sR, sR + (PI + (PI - sR) * 2), baseColor, 2);
// 畫紅色圓弧
drawCanvas(cWidth/2, cHeight/2, 80, sR, endRadian, coverColor, 2);
// 畫紅色圓頭
// 紅色圓頭其實就是一個圓,關鍵的是找到其圓心,涉及到三角函數知識,自己畫個圖一看就明了
var angle = 2*PI - endRadian; // 轉換成逆時針方向的弧度(三角函數中的)
xPos = Math.cos(angle) * 80 + cWidth/2; // 紅色圓 圓心的x坐標
yPos = -Math.sin(angle) * 80 + cHeight/2; // 紅色圓 圓心的y坐標
drawCanvas(xPos, yPos, 2, 0, 2*PI, coverColor, 2);
// 數字
cxt.fillStyle = coverColor;
cxt.font = '40px PT Sans';
var textWidth = cxt.measureText(text+'%').width;
cxt.fillText(text+'%', cWidth/2 - textWidth/2, cHeight/2 + 15);
text++;
if (endRadian.toFixed(2) >= finalRadian.toFixed(2)) {
clearInterval(timer);
}
}, 30);
function drawCanvas(x,y,r,sRadian,eRadian,color,lineWidth) {
cxt.beginPath();
cxt.lineCap = "round";
cxt.strokeStyle = color;
cxt.lineWidth = lineWidth;
cxt.arc(x, y, r, sRadian, eRadian, false);
cxt.stroke();
}
}
</script>
</body>
</html>關于動畫部分,可以使用requestAnimationFrame做優(yōu)化,函數改寫如下:
function draw(percent, sR) {
if (percent < 0 || percent > 100) {
return;
}
if (sR < Math.PI/2 || sR >= 3/2 * Math.PI) {
return;
}
var canvas = document.querySelector('#canvas'),
cxt = canvas.getContext('2d'),
cWidth = canvas.width,
cHeight = canvas.height,
baseColor = '#e1e1e1',
coverColor = '#fe4d43',
PI = Math.PI,
sR = sR || 1/2 * PI; // 默認圓弧的起始點弧度為π/2
var finalRadian = sR + ((PI + (PI - sR) * 2) * percent / 100); // 紅圈的終點弧度
var step = (PI + (PI - sR) * 2)/100; // 一個1%對應的弧度大小
var text = 0; // 顯示的數字
window.requestAnimationFrame(paint);
function paint() {
cxt.clearRect(0, 0, cWidth, cHeight);
var endRadian = sR + text * step;
// 畫灰色圓弧
drawCanvas(cWidth/2, cHeight/2, 80, sR, sR + (PI + (PI - sR) * 2), baseColor, 2);
// 畫紅色圓弧
drawCanvas(cWidth/2, cHeight/2, 80, sR, endRadian, coverColor, 2);
// 畫紅色圓頭
// 紅色圓頭其實就是一個圓,關鍵的是找到其圓心,涉及到三角函數知識,自己畫個圖一看就明了
var angle = 2*PI - endRadian; // 轉換成逆時針方向的弧度(三角函數中的)
xPos = Math.cos(angle) * 80 + cWidth/2; // 紅色圓 圓心的x坐標
yPos = -Math.sin(angle) * 80 + cHeight/2; // 紅色圓 圓心的y坐標
drawCanvas(xPos, yPos, 2, 0, 2*PI, coverColor, 2);
// 數字
cxt.fillStyle = coverColor;
cxt.font = '40px PT Sans';
var textWidth = cxt.measureText(text+'%').width;
cxt.fillText(text+'%', cWidth/2 - textWidth/2, cHeight/2 + 15);
text++;
if (endRadian.toFixed(2) < finalRadian.toFixed(2)) {
window.requestAnimationFrame(paint);
}
}
function drawCanvas(x,y,r,sRadian,eRadian,color,lineWidth) {
cxt.beginPath();
cxt.lineCap = "round";
cxt.strokeStyle = color;
cxt.lineWidth = lineWidth;
cxt.arc(x, y, r, sRadian, eRadian, false);
cxt.stroke();
}到此這篇關于詳解JavaScript+Canvas繪制環(huán)形進度條的文章就介紹到這了,更多相關JavaScript Canvas環(huán)形進度條內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Bootstrap CSS組件之按鈕組(btn-group)
這篇文章主要為大家詳細介紹了Bootstrap CSS組件之按鈕組(btn-group),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12
js substring從右邊獲取指定長度字符串(示例代碼)
本篇文章主要是對js substring從右邊獲取指定長度字符串的示例代碼進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12
JavaScript用20行代碼實現虎年春節(jié)倒計時
春節(jié)將至,相信大家跟小編一樣很激動呀。為了迎接虎年春節(jié)到來,小編為大家準備了一個虎年春節(jié)倒計時,僅20行代碼用js就實現啦。感興趣的可以動手試一試2022-01-01

