canvas-圓弧形可拖動進度條


使用方式

npm i drag-arc -S

import DragArc from 'drag-arc';

源碼地址:https://github.com/pangyongsheng/canvas-arc-draw

 

一、效果如下:

 

 

鏈接dome

二、

本文是實現可拖動滑塊實現的基本思路,及一個簡單的dome,(https://github.com/pangyongsheng/canvas-arc-draw

三、

1、首先在html中創建一個canvas標簽

<canvas id="canvas"  width="400" height="400"></canvas>

2、創建一個進度條對象,編寫初始化方法,獲取canvas對象及上下文環境;event方法是用來綁定事件(具體后面介紹);draw是用來繪圖的方法,這里把Draw對象的全部方法賦給draw方法;創建繪圖實例p,繪制初始圖形;

var Draw={
   init:function(){
    this.obj=document.getElementById("canvas");    //獲取canvas對象
    this.cObj=document.getElementById("canvas").getContext("2d");//獲取canvas對象上下文環境
    this.event();   //初始化事件
    this.pathr=120; //滑動路徑半徑
    this.draw.prototype=this; //draw繼承Draw方法
    this.p=new this.draw(112,284,18);  //創建實例p
  } 
  //... 
}

 

3、在Draw中編寫繪圖方法draw繪制下圖:

(1)創建繪圖方法,獲取參數

draw:function(x,y,r,j){  //繪圖
      this.cObj.clearRect(0,0,400,400);    //清空畫布
      this.x=x;   //滑塊坐標x
      this.y=y;   //滑塊坐標y 
      this.r=r;    //滑塊移動路徑半徑
      this.j=j;    //橙色圓弧結束弧度值
      //...
}

 (2)繪制內側圓弧

this.cObj.beginPath();
this.cObj.lineWidth = 1;
this.cObj.arc(200,200,100,Math.PI*0.75,Math.PI*2.25,false); // 繪制內層圓弧
this.cObj.strokeStyle = '#0078b4';
this.cObj.stroke();

(3)繪制外側圓弧

this.cObj.beginPath();
this.cObj.arc(200,200,120,Math.PI*0.75,Math.PI*2.25,false); // 繪制外側圓弧
this.cObj.strokeStyle = '#c0c0c0';
this.cObj.lineCap = "round";
this.cObj.lineWidth = 20;
this.cObj.stroke();

(4)繪制滑塊

  由於滑塊是可以移動的這里滑塊的位置使用了坐標參數xy,及滑塊半徑r作為可變參數

this.cObj.beginPath();
this.cObj.moveTo(200,200);
this.cObj.arc(x,y,r,0,Math.PI*2,false); // 繪制滑塊
this.cObj.fillStyle='#f15a4a';
this.cObj.fill();

this.cObj.beginPath();
this.cObj.moveTo(200,200);
this.cObj.arc(x,y,11,0,Math.PI*2,false); // 繪制滑塊內側白色區域
this.cObj.fillStyle='#ffffff';
this.cObj.fill();

 (5)繪制長度可變弧(橙色部分):

由於長度可變,這里把閉合弧度作為可變參數

this.cObj.beginPath();
this.cObj.arc(200,200,120,Math.PI*0.75,this.j,false); // 可變圓弧
this.cObj.strokeStyle = '#f15a4a';
this.cObj.lineCap = "round";
this.cObj.lineWidth = 20;
this.cObj.stroke();

 

至此繪圖方法完成,調用drow方法並傳入參數滑塊坐標、半徑和拖動弧度(x,y,r,j)即可完成圖片的繪制。

4、繪圖方法分析

(1)這里首先建立以canvas左上角為原點屏幕坐標系,后面的繪圖都將基於該坐標系,坐標圖像如下:

編寫獲取當前光標位置點相對canvas坐標系(lx,ly)的方法:即當前坐標點減去canvas偏移距離

  getx:function(ev){  //獲取鼠標在canvas內坐標x
    return ev.clientX-this.obj.getBoundingClientRect().left;
  },
  gety:function(ev){  //獲取鼠標在canvas內坐標y
    return ev.clientY-this.obj.getBoundingClientRect().top;
  }

(2)為方便構建圓的方程,這里建立一個以canvas中心為原點的坐標系,如下圖,在實際使用draw方法繪圖時使用的是黑色的坐標系,在使用圓的路徑處理是我們使用紅色的坐標系

下面添加坐標轉化方法,

屏幕坐標(黑色坐標)->中心坐標(紅色坐標)

 

spotchange:function(a){ //屏幕坐標轉化為中心坐標 
    var target={};
    if(a.x<200 && a.y<200){      //二象限
        target.x=-(200-a.x); 
        target.y=200-a.y; 
    }else if(a.x>200 && a.y<200){  //一象限  
        target.x=a.x-200; 
        target.y=200-a.y; 
    }else if(a.x>200 && a.y>200){  //四象限
        target.x=a.x-200;
        target.y=-(a.y-200) 
    }else if(a.x<200 && a.y>200){  //三象限
        target.x=-(200-a.x); 
        target.y=-(a.y-200); 
    } 
    return target; 
},

 

中心坐標(紅色坐標)->屏幕坐標(黑色坐標)

respotchange:function(a){ //中心坐標轉化為屏幕坐標
    var target={};
    if(a.x>0 && a.y>0){
      target.x=200+a.x;
      target.y=(200-a.y);
    }else if(a.x<0 && a.y>0){
      target.x=200+a.x;
      target.y=200-a.y;
    }else if(a.x<0 && a.y<0){
      target.x=200+a.x;
      target.y=-(a.y-200)
    }else if(a.x>0 && a.y<0){
      target.x=200+a.x;
      target.y=-(a.y-200);
    }
    return target;
  },

 

 

(3)滑塊路徑及位置計算方法

  首先不考慮xy正負,

  計算光標位置點的正切值

  tanφ = ly/lx;

  可知φ

  φ=arctan(tanφ)

  根據圓的參數方程,可獲得光標點對應藍色路徑位置坐標為 

  x=rcosφ

  y=rsinφ

(4)根據上面思路編寫獲取坐標位置方法,這里添加了xy和弧度值正負處理方法和可拖動弧度范圍

  getmoveto:function(lx,ly){
      if(!this.p.isDown){    //是否可移動
        return false;
      }
      var tem={};    //存放目標坐標位置
      tem.o=Math.atan(ly/lx); //鼠標移動點圓形角
      tem.x=this.pathr*Math.cos(tem.o);
      tem.y=this.pathr*Math.sin(tem.o);
      if(lx<0){ //坐標點處理(正負)
        tem.x=-tem.x;
        tem.y=-tem.y;
      }
     if(lx>0){  //弧度值處理
      tem.z=-Math.atan(tem.y/tem.x)+Math.PI*2;
     }else{
      tem.z=-Math.atan(tem.y/tem.x)+Math.PI;
     }
     if(tem.z>7.06){  //最大值
      tem.z=7.06;
      tem.x=this.pathr*Math.cos(Math.PI*2.25);
      tem.y=-this.pathr*Math.sin(Math.PI*2.25);
     }
     if(tem.z<2.4){ //最小值
      tem.z=2.4;
      tem.x=this.pathr*Math.cos(Math.PI*0.75);
      tem.y=-this.pathr*Math.sin(Math.PI*0.75);
     }
    return tem;
   },

 

(5)以上方法在canvas內任意點均可作為滑塊拖動的目標點,這里編寫cheack方法,將限制可拖動位置限制在一個大概的環形里

check:function(x,y){  //限制可拖動范圍
    var xx=x*x;
    var yy=y*y;
    var rr=114*114; //最小
    var rrr=126*126;  //最大
    if(xx+yy>rr && xx+yy<rrr){
      return true;
    }
    return false;
  },

 

5、事件方法編寫

(1)鼠標按下執行方法OnMouseDown

這里使用了getx和gety獲取光標相對canvas坐標,並判斷鼠標是否移動到了滑塊上方位置內,(this.p是當前繪圖對象,p.x即滑塊橫坐標,p.x即當前縱坐標,p.r即滑塊最大半徑),如果光標在滑塊上方則設置isDown為TRUE,反正依然,后面我們會通過isDown來判斷是否執行移動滑塊的方法:

OnMouseDown:function(evt){
    var X=this.getx(evt);    //獲取當前鼠標位置橫坐標
    var Y=this.gety(evt);     //獲取當前鼠標位置縱坐標
    var minX=this.p.x-this.p.r;  
    var maxX=this.p.x+this.p.r;
    var minY=this.p.y-this.p.r;
    var maxY=this.p.y+this.p.r;
     if(minX<X && X<maxX && minY<Y && Y<maxY){   //判斷鼠標是否在滑塊上 
         this.p.isDown=true;      
     }else{
          this.p.isDown=false;
     }
}

 

(2)鼠標按下后移動時滑塊的方法:

   OnMouseMove:function(evt){ //
       if(this.p.isDown){    //是否在滑塊上按下鼠標
          var a={};         //存放當前鼠標坐標
          a.x=this.getx(evt);    //坐標轉化
          a.y=this.gety(evt);
          var b=this.spotchange(a);    //坐標轉化
          var co=this.getmoveto(b.x,b.y);    //獲取要移動到的坐標點
          if(this.check(b.x,b.y)){    //判斷移動目標點是否在可拖動范圍
            var co=this.getmoveto(b.x,b.y);    //獲取到移動的目標位置坐標()
            var tar=this.respotchange(co);    //坐標轉化
            var o=co.z;
            this.p.draw(tar.x,tar.y,this.p.r,o);    //繪圖
          }
       }
   },

 (3)鼠標釋放方法

OnMouseUp:function(){  //鼠標釋放
       this.p.isDown=false
},

 

(4)最后將所有方法和事件綁定

event:function(){  //事件綁定
       this.obj.addEventListener("mousedown",this.OnMouseDown.bind(this),false);
       this.obj.addEventListener("mousemove",this.OnMouseMove.bind(this),false);
       this.obj.addEventListener("mouseup",this.OnMouseUp.bind(this),false);
   },

 

至此可拖動滑塊基本方法編寫完成

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM