canvas 图片编辑(拖拽旋转缩放)交流

youryida 2013-12-16 11:09:33
需要做一个在canvas里对图片进行拖拽、缩放、旋转的一个小应用。

现在可以拖拽,旋转有个问题,不好解决,demo文件在下面,大概80行代码的样子,希望路过的朋友指点下,谢谢!(我觉得问题出在转换坐标系过程了,但是不是很明白,求指点。)

http://youryida.duapp.com/other/drag_rotate/


...全文
3059 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Super_Melody 2016-08-28
  • 打赏
  • 举报
回复
终于找到自己想要的代码了,感谢楼主的分享精神,赞一个。
婉程序 2016-03-30
  • 打赏
  • 举报
回复
楼主你那有没有在canvas里对图片进行拖拽、缩放、旋转的多点触控事件代码?
海阔天空--L 2014-03-26
  • 打赏
  • 举报
回复
在火狐上不行....
destiny1231500 2013-12-24
  • 打赏
  • 举报
回复
test-2.3 不错 支持一下楼主 谢谢分享
youryida 2013-12-23
  • 打赏
  • 举报
回复
引用 7 楼 KK3K2005 的回复:
不好意思最近忙死天天加班到深夜 星期天有时间我来看下矩阵做法
嗯,老兄你有空了再整就行,注意身体! 借此楼发布一下我的终极成果:图片的拖拽与旋转(坐标转换、状态保存)
KK3K2005 2013-12-21
  • 打赏
  • 举报
回复
不好意思最近忙死天天加班到深夜 星期天有时间我来看下矩阵做法
zhjdg 2013-12-21
  • 打赏
  • 举报
回复
youryida 2013-12-20
  • 打赏
  • 举报
回复
每次在csdn上问问题都是这样,好几天无人光顾,最后还是自己整出来了... 研究过程我写在了我的博客里了,欢迎交流。 canvas 图片拖拽+旋转 [坐标变换] demo

<!doctype html>
<html>
<head>
	<title> </title>
	<meta http-equiv="X-UA-Compatible" content="IE=9"> 
	<meta charset="utf-8" />
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">
	<style>
		#canvas{border:1px solid #ccc;}
	</style>
   	
</head>
<body>
	<canvas id="canvas" width="500" height="300"></canvas>
	<pre>
功能:拖拽+旋转
思路:始终保持图片中心点在canvas坐标系的原点处,图片的每一次重绘都基于canvas坐标系的原点来绘制,即drawImage(img,-imgW/2,-imgH/2)。
	移动、旋转的时候绘制方法不变,变换的是canvas坐标系。
关键:理解屏幕坐标系和canvas坐标系的关系。将鼠标事件的屏幕坐标,转换为canvas坐标系中的坐标。
	计算旋转时每一次mousemove,在旋转前的canvas坐标系中move的角度。
	</pre>	
	<script>
	var cvs =document.getElementById("canvas");   
	var ctx =cvs.getContext("2d");
	var cvsH=cvs.height;
	var cvsW=cvs.width;
	var beginX,beginY;
	var LT={x:30,y:30};//图片左上角的点
	var Selected_Round_R=12;
	var isDown=false;
	var imgH,imgW;
	var moveAble=false,rotateAble=false;
	var img = new Image();	
	var rotate_radian=0;//canvas坐标系x轴与屏幕坐标系X轴夹角弧度
	img.src ="img/niuniu.jpg";
	img.onload=function (){
		imgH=img.height;
		imgW=img.width;
		PO={x:LT.x+imgW/2,y:LT.y+imgH/2};
		ctx.translate(PO.x,PO.y);//载入时将canvas坐标系原点移到图片中心点上
		onDraw();
		
	}
	function onDraw(){
		ctx.clearRect(-cvsW,-cvsH,2*cvsW,2*cvsH);
		ctx.drawImage(img,-imgW/2,-imgH/2);	
		//旋转控制旋钮
		ctx.beginPath();
		ctx.arc(0,-imgH/2-Selected_Round_R,Selected_Round_R,0,Math.PI*2,false);
		ctx.closePath();
		ctx.lineWidth=2;
        ctx.strokeStyle="#0000ff";
		ctx.stroke();
	}
	cvs.addEventListener("mousedown", startMove, false); 
	cvs.addEventListener("mousemove", moving, false);
	cvs.addEventListener("mouseup", endMove, false);	 	
	cvs.addEventListener("mouseout",endMove, false);

	function imgIsDown(x,y){
		return (-imgW/2<=x && x<=imgW/2 && -imgH/2<y && y<=imgH/2);
	}
	function RTIsDown(x,y){
		var round_center={x:0,y:-imgH/2-Selected_Round_R};
		var bool=getPointDistance({x:x,y:y},round_center)<=Selected_Round_R;
		return bool;
	}
	function startMove(){
		event.preventDefault();
		isDown=true;
		var loc=getEvtLoc();//获取鼠标事件在屏幕坐标系的位置(原点在canvas标签左上角)
		var x=loc.x,y=loc.y;
		beginX=x,beginY=y;
		var cLoc=convertCoor(loc);
		var Xc=cLoc.x,Yc=cLoc.y;
		moveAble=imgIsDown(Xc,Yc);
		rotateAble=RTIsDown(Xc,Yc);		
		if (moveAble) cvs.style.cursor="move";
		if (rotateAble) cvs.style.cursor="crosshair";
	}
	function moving(){
		event.preventDefault();
		if(isDown==false) return;
		var loc=getEvtLoc();
		if(moveAble){
			var x=loc.x,y=loc.y;
			var dx=x-beginX,dy=y-beginY;
			var mPO={x:PO.x+dx,y:PO.y+dy};//因为鼠标移动dx dy,所以PO在屏幕坐标系的坐标也 移动dx dy
			var cPO=convertCoor(mPO);//屏幕坐标系移动后的PO转换成canvas坐标系的坐标
			ctx.translate(cPO.x,cPO.y);//canvas坐标系原点移动到新的图片中心点		
			onDraw();
			
			PO.x=PO.x+dx;//记录下屏幕坐标系上PO的坐标变化
			PO.y=PO.y+dy;
			beginX=x,beginY=y;//记录移动后鼠标在屏幕坐标系的新位置	
		}else if(rotateAble){
			var cLoc=convertCoor(loc);
			var Xc=cLoc.x,Yc=cLoc.y;
			var newR = Math.atan2(Xc,-Yc);//在旋转前的canvas坐标系中 move的角度(因为旋钮在上方,所以跟,应该计算 在旋转前canvas坐标系中,鼠标位置和原点连线 与 y轴反方向的夹角)
			ctx.rotate(newR);
			rotate_radian+=newR;
			onDraw();
		}
	}
	function endMove(){
		event.preventDefault();
		isDown=false;
		moveAble=rotateAble=false;
		cvs.style.cursor="auto";
	}

	function getEvtLoc(){//获取相对canvas标签左上角的鼠标事件坐标
		return {x:event.offsetX,y:event.offsetY}
	}
	
	function convertCoor(P) {//坐标变换 屏幕坐标系的点 转换为canvas坐标系的点
		var x=P.x-PO.x;//在屏幕坐标系中,P点相对canvas坐标系原点PO的偏移
		var y=P.y-PO.y; 

		if(rotate_radian!=0){
			var len = Math.sqrt(x*x + y*y);
			var oldR=Math.atan2(y,x);//屏幕坐标系中 PO与P点连线 与屏幕坐标系X轴的夹角弧度			
			var newR =oldR-rotate_radian;//canvas坐标系中PO与P点连线 与canvas坐标系x轴的夹角弧度
			x = len*Math.cos(newR);
			y = len*Math.sin(newR);      		
		}
		
		return {x:x,y:y};
	}
	//获取两点距离
	function getPointDistance(a,b){
		var x1=a.x,y1=a.y,x2=b.x,y2=b.y;
		var dd= Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
		return dd;
	}
	</script>
</body>
</html>
youryida 2013-12-20
  • 打赏
  • 举报
回复
引用 3 楼 KK3K2005 的回复:
矩阵~~~ .... 你可以先弄弄看 晚上时间多 可以帮你一起看下
大神,我研究出来了,不过我还是很想看看使用矩阵是怎么做的? 这是我的链接 http://youryida.duapp.com/demo_canvas/coor_convert_move_rotate.html
youryida 2013-12-17
  • 打赏
  • 举报
回复
引用 3 楼 KK3K2005 的回复:
矩阵~~~ 最终显示 = 正常 * 矩阵 .... 你可以先弄弄看 晚上时间多 可以帮你一起看下
就喜欢爽快的大神,非常期待!今天搞了一天没搞出名堂来,燥死我了! 先行谢过了啊!!
KK3K2005 2013-12-17
  • 打赏
  • 举报
回复
矩阵~~~ 最终显示 = 正常 * 矩阵 旋转操作就是获取一个 旋转矩阵 那么你的鼠标坐标定位判断要 / 旋转矩阵 鼠标坐标/矩阵 == 图片原始区域内 则判断在图片里 好吧 上面是理论 不过根据一致性原则 应该是 ok的 你可以先弄弄看 晚上时间多 可以帮你一起看下
youryida 2013-12-17
  • 打赏
  • 举报
回复
好吧,小伙伴儿们,我自己有些进展了,我整理了下,目前需要解决的问题,有两个: 一、计算mousemove旋转时产生的角度; 二、判断旋转之后再拖拽时,mousedown的点是否在图片区域内。 我现在有一些解决思路,但是我数学不好,自己研究可能会花很长一段时间,希望路过的大神能出个demo让小弟参考下! QQ:1140215489 百度知道 100分悬赏 http://zhidao.baidu.com/question/2201564571024171668.html

39,118

社区成员

发帖
与我相关
我的任务
社区描述
HTML5是构建Web内容的一种语言描述方式。HTML5是互联网的下一代标准,是构建以及呈现互联网内容的一种语言方式.被认为是互联网的核心技术之一。
社区管理员
  • HTML5社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧