1. 程式人生 > >canvas translate 移動座標系實現圖形拖拽

canvas translate 移動座標系實現圖形拖拽

平移變換實質上是平移座標系, 而對於translate()傳入的引數,是新座標系相對於舊座標系的偏移量。

方法一:

平移座標系並繪製圖形後,恢復狀態,將座標系平移回原點(即重新以canvas的左上角為座標系原點)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>canvas拖拽</title>
</head>
<canvas id="myCanvas" width="400" height="400"></canvas>  
<body>
<script>
var Draw={
		translateX: 45,
		translateY:45,
		coordinateX:0,
		coordinateY:0,
		w:70,
		h:70,
		color:"red",
         init:function(){
        	 this.targetCanvas = document.getElementById("myCanvas");
             this.cObj=this.targetCanvas.getContext("2d");
             this.event()
             this.draw.prototype=this
             this.p=new  this.draw(this.coordinateX, this.coordinateY)
         },
         draw:function(coordinateX, coordinateY){        	  
        	 this.cObj.save();
                 //clearRect()方法清空當前畫布
        	 this.cObj.clearRect(0,0, this.targetCanvas.offsetWidth, this.targetCanvas.offsetHeight); 
        	 this.coordinateX = coordinateX;
        	 this.coordinateY = coordinateY;
        	 this.cObj.translate(this.coordinateX, this.coordinateY);
        	 this.cObj.beginPath();
        	 this.cObj.moveTo(0, 0);
        	 this.cObj.lineTo(30,0);
        	 this.cObj.moveTo(0, 0);
        	 this.cObj.lineTo(0,30);
        	 this.cObj.stroke();
        	 
        	 this.cObj.strokeStyle=this.color;
        	 this.cObj.strokeRect(this.translateX, this.translateY, this.w, this.h);
        	 this.cObj.restore(); //恢復狀態,將座標系平移回原點(即重新以canvas的左上角為座標系原點)
         },
         OnMouseMove:function(evt){
             if(this.p.isDown){
                //把(evt.offsetX,evt.offsetY)移動過程中的滑鼠點作為矩形的中心點
                 var coordinateX = evt.offsetX - this.p.w/2 - this.translateX;
                 var coordinateY = evt.offsetY- this.p.h/2 - this.translateY;
                 this.draw(coordinateX, coordinateY);                
             }
  
         },
         OnMouseDown:function(evt){
             var X=evt.offsetX;
             var Y=evt.offsetY;
             var rectOffsetX = X - this.coordinateX - this.translateX;
             var rectOffsetY = Y - this.coordinateY - this.translateY;
             if( rectOffsetX >0 && rectOffsetX <this.w){
            	 if(rectOffsetY >0 && rectOffsetY <this.h){
            		 this.p.isDown=true;
            	 }
             }else{
            	 this.p.isDown=false;
             }
             
         },
         OnMouseUp:function(){
             this.p.isDown=false
         },
         event:function(){
             var canvas=document.getElementById("myCanvas")
             canvas.addEventListener("mousedown",this.OnMouseDown.bind(this),false);
             canvas.addEventListener("mousemove",this.OnMouseMove.bind(this),false);
             canvas.addEventListener("mouseup",this.OnMouseUp.bind(this),false);
         }
     }
      Draw.init()
</script>
</body>
</html>

方法二:

使用變數coordinateX、coordinateY 記錄每次移動後坐標系原點相對canvas左上角的座標,不使用save()、restore()恢復狀態。

canvas translate部落格中有談到在移動座標系後,要不要恢復狀態的問題。其實不恢復狀態也是可以的,用變數儲存新座標系原點的相對座標就行。

在該方法中,也不再使用移動過程中的滑鼠點作為矩形的中心點,而是計算得出滑鼠在移動過程中的偏移量,並把該偏移量作為座標系的偏移量,即translate()的引數。

這個計算座標系偏移的演算法顯然更有現實意義。滑鼠在矩形內就可進行拖拽,拖拽完成後滑鼠在矩形內的位置應該不變,而不是變成矩形的中心。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>canvas拖拽</title>
</head>
<canvas id="myCanvas" width="1200" height="400"></canvas>  
<body>
<script>
//移動座標系,不使用save()、restore()恢復狀態
//通過使用coordinateX、coordinateY記錄座標系原點相對canvas左上角的座標

var Draw={
		coordinateX:0,  //記錄座標系原點相對canvas左上角的座標
		coordinateY:0,
		translateX: 45,  //矩形相對座標系原點的偏移量,固定值
		translateY:45,
		w:70,  //矩形寬度,固定值
		h:70,
		color:"red",
         init:function(){
        	 this.targetCanvas = document.getElementById("myCanvas");
             this.ctx=this.targetCanvas.getContext("2d");
             this.event()
             this.draw.prototype=this
             this.p=new  this.draw()
         },
         translate: function(x, y, disablePlot) {   //移動座標系
             this.coordinateX += x;  //加上座標系的偏移量,coordinateX得到的是新座標系的原點相對canvas左上角的座標
             this.coordinateY += y;   
             this.ctx.translate(x, y);  //座標系的偏移量等於滑鼠的偏移量
           },
         draw:function(){        	  
        	 var canvasWidth = this.targetCanvas.offsetWidth, canvasHeight = this.targetCanvas.offsetHeight;
        	 this.ctx.clearRect(-canvasWidth, -canvasHeight, canvasWidth*2, canvasHeight*2);
        	 this.ctx.strokeStyle=this.color;
        	 this.ctx.beginPath();
        	 this.ctx.moveTo(0, 0);
        	 this.ctx.lineTo(30,0);
        	 this.ctx.moveTo(0, 0);
        	 this.ctx.lineTo(0,30);
        	 this.ctx.stroke();       	        	 
        	 this.ctx.strokeRect(this.translateX, this.translateY, this.w, this.h);
         },
         OnMouseMove:function(evt){
             if(this.p.isDown){
                 var mouseOffsetX = evt.offsetX - this.p.mouseStartPoint.x;
                 var mouseOffsetY = evt.offsetY - this.p.mouseStartPoint.y;  //記錄滑鼠在移動過程中的偏移量
                 this.p.mouseStartPoint = {x: evt.offsetX, y: evt.offsetY}; //重置滑鼠偏移量的開始點
                 this.translate(mouseOffsetX, mouseOffsetY);
                 this.draw();                
             }
  
         },
         OnMouseDown:function(evt){
             var X=evt.offsetX;
             var Y=evt.offsetY;
             var rectOffsetX = X - this.coordinateX - this.translateX;
             var rectOffsetY = Y - this.coordinateY - this.translateY;
             if( rectOffsetX >0 && rectOffsetX <this.w){
            	 if(rectOffsetY >0 && rectOffsetY <this.h){
            		 this.p.isDown=true;
            		 this.p.mouseStartPoint = {x:X, y:Y};
            	 }
             }else{
            	 this.p.isDown=false;
             }
             
         },
         OnMouseUp:function(){
             this.p.isDown=false
         },
         event:function(){
             var canvas=document.getElementById("myCanvas")
             canvas.addEventListener("mousedown",this.OnMouseDown.bind(this),false);
             canvas.addEventListener("mousemove",this.OnMouseMove.bind(this),false);
             canvas.addEventListener("mouseup",this.OnMouseUp.bind(this),false);
         }
     }
      Draw.init()
</script>
</body>
</html>

最終效果: