canvas實現儀表盤

根據項目要求,要實現這樣一個儀表盤的效果:html


clipboard.png


拿到圖以後首先作一個拆分,分紅幾個小模塊。從裏往外看,首先須要一個內環的刻度條,這個內環刻度條由若干個點構成,因此個人實現方式爲:先畫一根線,經過循環,旋轉獲得一個圓形的刻度條算法

//innerLineNums 爲刻度數量
ctx.save(); 
for (var i = 0; i <= $this.innerLineNums; i++) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'rgba(155,157,183,1)';               
    ctx.moveTo(82, 0);
    ctx.lineTo(80, 0);
    ctx.stroke();
    //每一個點的弧度,360°弧度爲2π,即旋轉弧度爲 2π / 75
    ctx.rotate(2*Math.PI / $this.innerLineNums);
}                      
ctx.restore();

其次再是裏面的長刻度線,以及數字標誌,還有中間的文字sql

// 內環刻度線
ctx.save();
for (var i = 0; i < 6; i++) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'rgba(155,157,183,1)';
    ctx.moveTo(82, 0);
    ctx.lineTo(78, 0);
    ctx.stroke();

    //每10個點分一個刻度,共5個刻度,旋轉角度爲deg1 * 10
    ctx.rotate(deg1 * 10);
}
ctx.restore();

//內環刻度上面數字
ctx.save();
ctx.rotate(Math.PI / 2);
for (i = 0; i < 6; i++) {
    ctx.fillStyle = 'rgba(165,180,198, .4)';
    ctx.font = '10px Microsoft yahei';
    ctx.textAlign = 'center';
    ctx.fillText(20 * i, 0, -65);
    ctx.rotate(deg1 * 10);
}
ctx.restore();

//內環文字
ctx.save();
ctx.rotate(210 * Math.PI / 180);
ctx.fillStyle = '#000';
ctx.font = '44px Microsoft yahei';
ctx.textAlign = 'center';
ctx.textBaseLine = 'top';
ctx.fillText(process, 0, 10);
var width = ctx.measureText(process).width;

ctx.fillStyle = '#000';
ctx.font = '20px Microsoft yahei';
ctx.fillText('分', width / 2 + 10, 10);

好了,此時內環的效果已經有了,能夠看到以下效果:canvas

clipboard.png

再來看外環的刻度條,外環刻度條有一個缺口,目測估算一下,算缺口爲1/3,即外環的刻度線須要畫120-360°,咱們這裏分數滿分爲100分,從0開始,爲了方便計算就給他畫50根刻度線,那麼每根刻度線的角度deg1的算法爲:this

//弧長計算公式是一個數學公式,爲L=n(圓心角度數)× π(1)× r(半徑)/180(角度制),L=α(弧度)× r(半徑) (弧度制)。其中n是圓心角度數,r是半徑,L是圓心角弧長。
//整個運動的角度是(360-120)度,轉換成弧度就是12π/9,一共分紅了50個分數段,那麼每個分數段就是12π/450 = 2π / 75
//如需旋轉 5 度,可規定下面的公式:5*Math.PI/180。            
deg1() {
    return (Math.PI * 12) / (9 * this.lineNums)
}

從這裏咱們知道了外環2/3個圓的刻度線爲50根,那麼內環整個圓的刻度線innerLineNums = 50 * 3 / 2 = 75根。好了,知道角度以後仍是按照以前的方法,畫一根線,而後循環,在旋轉,跳躍畫出灰色的外環刻度線:spa

// 細份內環刻度線
ctx.save();
for (var i = 0; i <= $this.innerLineNums; i++) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'rgba(155,157,183,1)';
    ctx.moveTo(82, 0);
    ctx.lineTo(80, 0);
    ctx.stroke();

    //每一個點的弧度,360°弧度爲2π,即旋轉弧度爲 2π / 75
    ctx.rotate(2 * Math.PI / $this.innerLineNums);
}
ctx.restore();

這個時候效果是這樣的:.net

clipboard.png

還差外環的漸變線,以及線上面的那個點,那根線是根據分數動態畫的,因此長度須要計算,我打算用一個圓弧來實現,上面說過每一個線之間的旋轉弧度爲deg1,那圓弧的長度就等於score * deg1 / 2,根據公式畫出線以下:rest

//色彩段數與彩色刻度條保持一致,線條無間隔,因此段數 * 2
var gradient = ctx.createLinearGradient(0, 0, $this.colorLineNums * 2, 0);
gradient.addColorStop("0", "rgba(252,3,44,.6)");
gradient.addColorStop("0.5", "rgba(134,37,168,.6)");
gradient.addColorStop("1.0", "rgba(54,63,255,.6)");

//外環漸變線
ctx.save();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = gradient;
ctx.arc(0, 0, radius, 0, angle, false);
ctx.stroke();
ctx.restore();

此時效果是這樣的:code

clipboard.png
還有圓外環綵線上面的圓點,能夠用一個小圓實現,而後改變他的x,y座標便可實現:htm

ctx.save();
ctx.beginPath();
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.arc(this.x, this.y, 5, 0, Math.PI * 2, false);
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = "rgba(246, 5, 51, 1)";
ctx.stroke();
ctx.restore();

ctx.save();
ctx.beginPath();
ctx.fillStyle = 'rgba(246, 5, 51, 1)';

ctx.arc(this.x, this.y, 3, 0, Math.PI * 2, false);
ctx.fill();

ctx.restore();

此時,還差個彩色的線,效果以下,額,這個彩色的線如何實現呢,剛開始也是不知如何下手,通過高人指點後,得出結局方案:把漸變色切割,多少根綵線就分割成多少份,而後感謝 嗑瓜子兒gf-顏色漸變的JS代碼 寫的博客,提供了算法
clipboard.png
最終效果出來了:

clipboard.png
預覽組件

第一次寫canvas組件,此代碼僅供參考,最後感謝[masqli-canvas仿芝麻信用分儀表盤][3],參考了前面兩位博主的代碼才能實現我項目的需求,所謂前人栽樹,後人乘涼,今天把我寫的也分享給你們,能幫到你們就更好,對我本身也算作個筆記了,在此再次感謝兩位博主

相關文章
相關標籤/搜索