1、示例效果:html
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);
},複製代碼
至此可拖動滑塊基本方法編寫完成