canvas案例 -- 通过设定不同参数实现环形进度条

86 阅读1分钟

image.png

image.png

image.png

HTML结构

首先先构造一个div结构,里面放一个canvas和调节范围的结构(input[type="range"])。

    <div id="app">
        <canvas id="canvas" width="200" height="200" ></canvas>
        <input type="range" id="range" value="0">
    </div>

CSS结构

运用绝对定位的方式将canvas画布进行居中,还有进度条设置也居中并把它放在canvas画布下面。

        #app
        {
            position: relative;
            height: 100vh;
        }
        #app #canvas
        {
            position: absolute;
            
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
        }
        #app #range
        {
            position: absolute;
            top: 80%;
            left: 50%;
            transform: translate(-50%,0);
        }

JavaScript结构

接下来就是最重要的JavaScript结构了,主要使用了一些圆的函数进行解决。

        var range = document.getElementById("range");
      var canvas = document.getElementById("canvas");
      var cxt = canvas.getContext("2d");
      var cenX = canvas.width/2;
      var cenY = canvas.height/2;
      var progress = Math.PI*2/100;
      var steps=0;

     
      function DrawPro(cxt,steps){
      //绘制进度环
      cxt.clearRect(0,0,canvas.width,canvas.height);
      cxt.strokeStyle = "#dddddd";
      
      cxt.lineWidth=20;
      cxt.save();
      cxt.beginPath();
      cxt.arc(cenX,cenY,90,0,Math.PI*2,false);
      cxt.stroke();
      
      cxt.closePath();
      cxt.restore(); 
      cxt.fillStyle="rgb(247,213,0)"
      cxt.save();
      cxt.beginPath();
      cxt.arc(cenX,cenY,80,0,Math.PI*2,false);
      cxt.fill();
      
      cxt.closePath();
      cxt.restore(); 

      cxt.strokeStyle="skyblue";
      cxt.lineWidth=20;
      cxt.save();
      cxt.beginPath();
      cxt.arc(cenX,cenY,90,-Math.PI/2,-Math.PI/2+steps*progress,false);
      cxt.stroke();
      cxt.closePath();
      cxt.restore();
               //绘制字体
      cxt.fillStyle="#000000";
      cxt.font="bold 26px Poppin";
      cxt.save();
      cxt.beginPath();
      //考虑了数字的个数 如果是100三位数字的位置和两位数字
      if(steps.toFixed(0).length==3){
          cxt.fillText(steps.toFixed(0)+"%",cenX-30,cenY+10);
      }else if(steps.toFixed(0).length==1){
          cxt.fillText(steps.toFixed(0)+"%",cenX-17,cenY+10);
      }else{
          cxt.fillText(steps.toFixed(0)+"%",cenX-22,cenY+10);
      }
      cxt.closePath();
      cxt.restore();
      //动态进度小球
      cxt.fillStyle="white";
      cxt.save();
      cxt.beginPath();
      cxt.arc(90*Math.cos(Math.PI/2-(Math.PI*2*(steps/100)))+100,90*-Math.sin(Math.PI/2-(Math.PI*2*(steps/100)))+100,10,0,Math.PI*2,false);
      cxt.fill();
      cxt.closePath();
      cxt.restore();
      //静态进度小球
      cxt.fillStyle="white";
      cxt.save();
      cxt.beginPath();
      cxt.arc(100,10,10,0,Math.PI*2,false);
      cxt.fill();
      cxt.closePath();
      cxt.restore();


      }
      DrawPro(cxt,steps);
      range.addEventListener("input",()=>{
          steps = parseInt(range.value);
          DrawPro(cxt,steps);
          console.log(90*Math.cos(Math.PI/2-(Math.PI*2*(steps/100)))+100,90*-Math.sin(Math.PI/2-(Math.PI*2*(steps/100)))+100)
      })