canvas圓形可拖動進度條

1、示例效果:html

codepen.io/pangyongshe…
git


2、dome代碼github

本文是實現可拖動滑塊實現的基本思路,及一個簡單的dome,(github.com/pangyongshe…canvas

3、實現bash

一、首先在html中建立一個canvas標籤dom

<canvas id="canvas"  width="400" height="400"></canvas>複製代碼

二、建立一個進度條對象,編寫初始化方法,獲取canvas對象及上下文環境;event方法是用來綁定事件(具體後面介紹);draw是用來繪圖的方法,這裏把Draw對象的所有方法賦給draw方法;建立繪圖實例p,繪製初始圖形;ui

複製代碼
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
  } 
  //... 
}複製代碼
複製代碼

三、在Draw中編寫繪圖方法draw繪製下圖:this

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

複製代碼
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)繪製內側圓弧prototype

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)便可完成圖片的繪製。

四、繪圖方法分析

(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;
  },複製代碼
複製代碼

五、事件方法編寫

(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);
   },複製代碼

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

相關文章
相關標籤/搜索