2020年4月21日 星期二

[JavaScript]利用Canvas繪製儀表板

     雖然網路上有很多免費視覺化報表套件可以使用,但是想說利用原生JavaScript來自己畫畫看,實際上繪製起來還挺有趣的,就結果來說還算不錯的經驗。

     在研究的過程中發現Canvas配合JavaScript其實還挺強大,有心的話還可以做成動畫和遊戲。不過本篇內容只是簡單畫個儀表板出來。

內容如下:

HTML部分 放上canvas並訂定高寬即底色白

<canvas height="300" width="400" id="canvas" style="background: RGB(255,255,255);" ></canvas>


JavaScript部分

<script type="text/JavaScript">
    //傳入數字代表儀錶板要顯示的值,這邊簡單呼叫一下
    Draw(66);
  
    //iValue:值
    function Draw(iValue)
    {
        var Can = document.getElementById("canvas");
        var ctx = Can.getContext('2d');
       

        //初始化畫布狀態       
        ctx.translate(400,400);
        ctx.scale(0.6,0.6);
        ctx.strokeStyle = "black";
        ctx.lineCap = "round"
      
        //儲入
狀態
        ctx.save();
      
        //繪製顏色尺度
        //剪裁繪圖半圈

        ctx.beginPath()
        ctx.arc(0,0,295,Math.PI,Math.PI*2 ,false);
        ctx.clip();
      
        //Red: 0-60
        ctx.fillStyle = "RGB(241,84,91)";
        //紅半圈
        ctx.beginPath()
        ctx.arc(0,0,295,Math.PI*0.6,Math.PI*1.6 ,false);
        ctx.fill();
      
        //Yellow: 60-80
        ctx.fillStyle="RGB(255,249,117)";
        //黃半圈
        ctx.beginPath()
        ctx.arc(0,0,295,Math.PI*1.6,Math.PI*0.6 ,false);
        ctx.fill();
      
        //Green: 80-100
        ctx.fillStyle="RGB(117,255,186)";
        //綠半圈
        ctx.beginPath()
        ctx.arc(0,0,295,Math.PI*1.8,Math.PI*0.8 ,false);
        ctx.fill();
      
        //內圓盤 白色
        ctx.fillStyle = "White";
        ctx.beginPath()
        ctx.arc(0,0,270,Math.PI,Math.PI*2,false);
        ctx.fill();
      
        //取出狀態
        ctx.restore();
        //儲入
狀態
        ctx.save();
      
        //外圓盤弧線
        ctx.lineWidth = 5;
        ctx.beginPath()
        ctx.arc(0,0,300,Math.PI*0.95,Math.PI*0.05,false);       
        ctx.stroke();

        //刻度
        ctx.lineWidth = 2;
        //旋轉半圈
        ctx.rotate(Math.PI);
        //主刻度
        for (let i=0;i<=10;i++){
            //畫刻度
            ctx.beginPath();
            ctx.moveTo(275,0);
            ctx.lineTo(295,0);
            ctx.stroke();
          
            //順時鐘轉半圈/10
            ctx.rotate(Math.PI/10);
        }
      
        //取出
狀態
        ctx.restore();
        //儲入
狀態
        ctx.save();
      
        //主刻度值
        ctx.font = "15pt Arial";
        for (let i=0; i<=10; i++)
        {
            let r = 250;
            let x = Math.cos((Math.PI/10)*(10-i))*r - (i.toString().length)*10
            let y = Math.sin((Math.PI/10)*(10-i))*r
            ctx.fillText((i*10).toString(), x, -1*y);
        }
      
        //副刻度
        ctx.lineWidth = 2;
        //旋轉半圈
        ctx.rotate(Math.PI);  
        for (let i=0;i<=100;i++){
            //畫刻度(不畫10的倍數)
            if (i%10 != 0)
            {
                ctx.beginPath();
              
                //5的倍數刻度加長
                if (i%5 == 0)
                {
                    ctx.moveTo(280,0);
                }
                else
                {
                    ctx.moveTo(290,0);
                }
                ctx.lineTo(295,0);
                ctx.stroke();
            }
            //順時鐘轉半圈/100
            ctx.rotate(Math.PI/100);
        }
      
        //取出
狀態
        ctx.restore();
        //儲入
狀態
        ctx.save();
      
        //繪製指針 菱形
        ctx.lineWidth = 5;
      
        //
菱形長短邊
        let l = 200, s=50;
        //度數
        let r =30
      
        //轉
        ctx.rotate(Math.PI*( 1 + iValue/100) - r/180);
      
        ctx.beginPath();
        ctx.moveTo(0,0);
        ctx.lineTo(s,0);
        //轉
        ctx.rotate(r/180);
        ctx.lineTo(l+s,0);
      
        //轉
        ctx.rotate(r/180);
        ctx.lineTo(s,0);
      
        ctx.lineTo(0,0);
        ctx.fill();
      

        //取出狀態
        ctx.restore();
        //儲入狀態        
        ctx.save();
      
        //值
        ctx.font = "30pt Arial";
        ctx.fillText(iValue.toString() +'%', (iValue.toString().length + 1)*(-10), 50);
      
        //圓心圓盤
        ctx.lineWidth = 5

        ctx.beginPath();
        ctx.arc(0,0,10,0,Math.PI*2,true);

        ctx.stroke();
    }
</script> 

 
成品如下:



沒有留言:

張貼留言