平移变换实质上是平移坐标系, 而对于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>
最终效果: