原生JS使用Canvas实现拖拽式绘图功能
(编辑:jimmy 日期: 2024/11/28 浏览:3 次 )
一、实现的功能
1、基于oop思想构建,支持坐标点、线条(由坐标点组成,包含方向)、多边形(由多个坐标点组成)、圆形(包含圆心坐标点和半径)等实体
2、原生JavaScript实现,不依赖任何第三方js库和插件
3、多图形绘制(支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形绘制)
4、拖拽式绘制(鼠标移动过程中不断进行canvas重绘)
5、图片绘制(作为背景图片时重绘会发生闪烁现象,暂时有点问题,后面继续完善)
5、清空绘制功能
6、新版本优化绘制性能(使用共享坐标变量数组,减少了大量的对象创建操作)
7、新版本支持箭头绘制功能
二、完整实现代码
DrawingTools =(function(){ //公共方法 var getDom=function(id){return document.getElementById(id)}; var isNull=function(s){return s==undefined||typeof(s)=='undefined'||s==null||s=='null'||s==''||s.length<1}; var hideDefRM=function(){document.oncontextmenu=function(){return false}};//屏蔽浏览器默认鼠标事件 /**绘图容器*/ var cbtCanvas; /**绘图对象*/ var cxt; /**绘制的图形列表*/ var shapes=new Array(); var graphkind={'cursor':0,'pen':1,'line':2,'trian':3,'rect':4,'poly':5,'circle':6,'arrow':21,'parallel':41,'trapezoid':42}; //背景图片绘制配置 var bgPictureConfig={ pic:null,//背景图片地址或路径 repaint:true,//是否作为永久背景图,每次清除时会进行重绘 }; //加载并绘制图片(src:图片路径或地址),默认重绘背景图 var loadPicture=function(src){ if(isNull(bgPictureConfig.repaint)||bgPictureConfig.repaint){bgPictureConfig.pic=src} var img = new Image(); img.onload = function(){cxt.drawImage(img,0,0)} img.src =src; } //绘图基础配置 var paintConfig={lineWidth:1,//线条宽度,默认1 strokeStyle:'red',//画笔颜色,默认红色 fillStyle:'red',//填充色 lineJoin:"round",//线条交角样式,默认圆角 lineCap:"round",//线条结束样式,默认圆角 }; //重新载入绘制样式 var resetStyle=function(){ cxt.strokeStyle=paintConfig.strokeStyle; cxt.lineWidth=paintConfig.lineWidth; cxt.lineJoin=paintConfig.lineJoin; cxt.lineCap=paintConfig.lineCap; cxt.fillStyle=paintConfig.fillStyle; } //鼠标图形 var cursors=['crosshair','pointer']; /** 切换鼠标样式*/ var switchCorser=function(b){ cbtCanvas.style.cursor=((isNull(b)"选择:"+ctrlConfig.kind); //设置起始点 switch(ctrlConfig.kind){ case graphkind.pen://画笔(不松开鼠标按键一直画) beginDrawing();//开始绘制 cxt.beginPath(); cxt.moveTo(e.offsetX,e.offsetY); break; case graphkind.poly://多边形 var p=new Point(e.offsetX,e.offsetY); if(isDrawing()){ getCuGraph().add(p);//添加到 }else{//第一次确定开始坐标 beginDrawing();//开始绘制 setStartPoint(p); var poly=new Poly(); poly.add(p); setCuGraph(poly);//设置当前绘制图形 } break; case graphkind.line://线条 case graphkind.arrow://方向 case graphkind.trian://三角形 case graphkind.rect://矩形 case graphkind.parallel://平行四边形 case graphkind.trapezoid://梯形 beginDrawing();//开始绘制 var p=new Point(e.offsetX,e.offsetY); setStartPoint(p); var poly=new Poly(); poly.add(p); setCuGraph(poly);//设置当前绘制图形 break; case graphkind.circle://圆 console.log("确定图形绘制开始坐标点:"+e.offsetX+","+e.offsetY);//点击确定图形的开始坐标点 beginDrawing();//开始绘制 var p=new Point(e.offsetX,e.offsetY); setStartPoint(p); var circle= new Circle({'start':p}); setCuGraph(circle); break; case ctrlConfig.cursor: //手型鼠标 default://默认是手型鼠标,不允许绘制 } }else if(btnNum==2){ console.log("右键由于结束多边形绘制"); if(isDrawing()){ if(ctrlConfig.kind==graphkind.poly){ repaint(); getCuGraph().draw(); stopDrawing();//结束绘制 } } } hideDefRM();//屏蔽浏览器默认事件 } //鼠标移动(拖动,根据鼠标移动的位置不断重绘图形) var mouseMove = function(e){ if(isDrawing()&&hasStartPoint()){//检查是否开始绘制,检查是否有开始坐标点 //画笔不需要重绘 if(ctrlConfig.kind>1){ repaint();//重绘 } var p=setCuPointXY(e.offsetX,e.offsetY,0);//设置共享的临时坐标点,用于防止重复创建对象 switch(ctrlConfig.kind){ case graphkind.pen://画笔(一直画) cxt.lineTo(e.offsetX,e.offsetY); cxt.stroke(); break; case graphkind.poly://多边形 var poly=getCuGraph(poly); var size=poly.getSize(); poly.setPoint(p,(size-1)); poly.draw(); break; case graphkind.line://线条 var line=new Line(getStartPoint(),p,false); ctrlConfig.cuGraph=line; line.draw(); break; case graphkind.arrow://方向 var line=new Line(getStartPoint(),p,true); ctrlConfig.cuGraph=line; line.draw(); break; case graphkind.trian://三角形 var lu=getStartPoint(); var x2=p.getX(); var x1=lu.getX(); //三角形左边的点坐标计算方法:(x1-(x2-x1),y2) var x3=x1-(x2-x1); var l=setCuPointXY(x3,p.getY(),1);//设置共享的临时坐标点,用于防止重复创建对象 var poly=getCuGraph();//获取当前图形 poly.set([lu,p,l]); poly.draw();//即时绘制 break; case graphkind.parallel://平行四边形 var lu=getStartPoint(); var x3=p.getX(); var x1=lu.getX(); //平行四边形两个未知坐标点计算方法:(x1-(x3-x1),y3),(x1+(x3-x1),y1) var x2=x3+(x3-x1); var x4=x1-(x3-x1); var ld=setCuPointXY(x2,lu.getY(),1);//设置共享的临时坐标点,用于防止重复创建对象 var ru=setCuPointXY(x4,p.getY(),2);//设置共享的临时坐标点,用于防止重复创建对象 var poly=getCuGraph();//获取当前图形 poly.set([lu,ru,p,ld]); poly.draw();//即时绘制 break; case graphkind.trapezoid://梯形 var lu=getStartPoint(); var x3=p.getX(); var x1=lu.getX(); //梯形两个未知坐标点计算方法:(x3-(x3-x1)/2,y1),(x1-(x3-x1)/2,y3) var x2=x3-(x3-x1)/2; var x4=x1-(x3-x1)/2; var ld=setCuPointXY(x2,lu.getY(),1); var ru=setCuPointXY(x4,p.getY(),2); var poly=getCuGraph(); poly.set([lu,ru,p,ld]); poly.draw(); break; case graphkind.rect://矩形 var lu=getStartPoint(); //矩形右上角和左上角坐标计算方法 var ld=setCuPointXY(lu.getX(),p.getY(),1); var ru=setCuPointXY(p.getX(),lu.getY(),2); var poly=getCuGraph(); poly.set([lu,ru,p,ld]); poly.draw(); break; case graphkind.circle://圆 var circle=getCuGraph();//获取当前图形 circle.set({'start':getStartPoint(),'end':p}); circle.draw();//即时绘制 break; } } } //鼠标按键松开 var mouseUp = function(e){ if(isDrawing()){ //console.log("松开鼠标按键:"+e.offsetX+","+e.offsetY); //画笔不需要重绘 if(ctrlConfig.kind>1){ repaint(); getCuGraph().draw(); } if(ctrlConfig.kind!=graphkind.poly){//多边形绘制鼠标按键松开不结束绘制,多边形只有右键点击才能结束绘制 stopDrawing();//结束绘制 } } } //鼠标移出 var mouseOut = function(e){ console.log("鼠标移出绘制区域"+e.offsetX+","+e.offsetY); if(isDrawing()){ console.log("停止绘制"); if(ctrlConfig.kind>1){ repaint(); getCuGraph().draw(); } stopDrawing();//停止绘制 } } return{ isNull:isNull, getDom:getDom, clear:function(){ stopDrawing();//停止绘制 repaint(); }, /**初始化*/ init:function(params){ cbtCanvas=getDom(params.id); //浏览器是否支持Canvas if (cbtCanvas.getContext){ /**绘图对象*/ cxt=cbtCanvas.getContext("2d"); cbtCanvas.onmousedown = mouseDown; cbtCanvas.onmouseup = mouseUp; cbtCanvas.onmousemove = mouseMove; cbtCanvas.onmouseout = mouseOut; resetStyle();//载入样式 return true; }else{ return false; } }, /**设置背景图片*/ setBgPic:loadPicture, /**选择图形类型*/ begin:function(k){ console.log("选择绘制图形:"+k); if(isNaN(k)){//如果不是数字,先转换为对应字符 ctrlConfig.kind=kind[k]; }else{ ctrlConfig.kind=k; } switchCorser(true);//切换鼠标样式 }, /*手型,并停止绘图*/ hand:function(){ ctrlConfig.kind=0; stopDrawing();//停止绘制 switchCorser(false);//切换鼠标样式 } } })
三、使用方式
1、图形类型
0:鼠标,1:画笔,2:线条,3:三角形,4:矩形,5:多边形,6:圆形,21:箭头,41:平行四边形,42:梯形
var graphkind={'cursor':0,'pen':1,'line':2,'trian':3,'rect':4,'poly':5,'circle':6,'arrow':21,'parallel':41,'trapezoid':42};
2、初始化以及使用背景图片和画笔选择
var drawUtil=new DrawingTools(); //初始化,(如果浏览器不支持H5,会初始化失败,返回false) if(drawUtil.init({'id':'calibrationCanvas'})){ //加载图片 var imgsrc='图片地址'; if(!drawUtil.isNull(imgsrc)){ drawUtil.setBgPic(imgsrc,true);//设置背景图片(异步加载图片) } } drawUtil.begin(1);//选择画笔
2、绘制箭头
drawUtil.begin(21);
总结
以上所述是小编给大家介绍的原生JS使用Canvas实现拖拽式绘图功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
下一篇:Node.js 路由的实现方法