目录
一、演示功能
二、原理实现
(1)、绘制图形
(2)、绘制逻辑原理
(3)、动画原理
(4)、图形变换原理
三、残留bug
四、源代码
一、演示功能
实现了绘制线、直线、矩形、圆 绘制时候还可以选择绘制属性(虚实线、填充图形、颜色)
可以执行图形变换操作
演示
二、原理实现
web端绘制都是使用canvas实现
(1)、绘制图形
以矩形来说明:
canvas绘制矩形API:
strokeRect(x,y,w,h)
fillRect(x,y,w,h)
绘制矩形需要一个点和长框就能绘制出矩形
(这个两个API我认为不好,不能绘制倾斜的矩形)
(2)、绘制逻辑原理
(绘制矩形矩形) 在鼠标按下左键的时候记录鼠标第一个点,同时在鼠标未弹起的过程中移动鼠标获得第二个鼠标的点,绘制矩形api只需要(x,y,w,h)通过计算第二个点和第一个点的坐标差值就能得到w和h
ctx.value.fillRect(Rect.frst.x, Rect.frst.y, Rect.last.x - Rect.frst.x, Rect.last.y - Rect.frst.y)
具体绘制代码(伪代码)
//绘制矩形function RectDraw(){//填充 ctx.fillRect(x,y,w,h);//边框 ctx.strokeRect(x,y,w,h)ctx.value.strokeStyle=Rect.color;ctx.value.fillStyle=Rect.color;//是否是虚线if(Rect.isdotted==='Y'){ctx.value.setLineDash([8,10]); //单个长度 之间距离}else {ctx.value.setLineDash([8,0]);}//是否是边框if (Rect.isBody==='Y') { //边框ctx.value.strokeRect(Rect.frst.x, Rect.frst.y, Rect.last.x - Rect.frst.x, Rect.last.y - Rect.frst.y)}else { //填充ctx.value.fillRect(Rect.frst.x, Rect.frst.y, Rect.last.x - Rect.frst.x, Rect.last.y - Rect.frst.y)}}
(3)、动画原理
绘制矩形时候的动画效果
本质: "清屏---绘制" 的重复
在绘制矩形的过程中 鼠标按下后 记录第一个点,在鼠标移动过程中获得第二点,鼠标持续移动会产生多个“第二个点”也就是会绘制多个大小不一的矩形,在绘制这一个个矩形重叠起来就是一个动画过程,而我们需要的是最新的那个矩形;只需要在绘制前进行清屏操作就能保证绘制的是最新的图形;
但在清屏的同时怎么做到不清除之前已经绘制好的图形呢?有小伙伴可能就说“直接局部清屏不就可以了嘛” ;不不不,没那么简单,局部清屏是不可控的。如果当前绘制图形在之前已经绘制好的图形附近或者图形上方(重叠)那么旧图形就会被“清屏”影响;
那么到底该怎么实现呢?且听听我的解决办法,这个为动画效果的“清屏” 不仅仅是清屏,它需要在清屏的后再绘制之前已经绘制完成的数据就能做到在绘制新图形的情况下不干扰旧图形。
那么怎么实现这个为动画而生的清屏方法呢?且听听我的解决办法,我把之前已经绘制完成的图形数据称为“死数据”,未绘制完成的图形数据称为“活数据”;什么时候算绘制完成呢?当鼠标左键按下后为开始准备绘制,鼠标移动执行重复绘制,当鼠标左键弹起即为绘制完成;这时候我们可以创建临时图形数据Rect来表示“活数据”,而“死数据”即为Rects是Rect的数组 ,当鼠标左键弹起的时候把当前Rect添加到Rects中保存。在清屏后再绘制Rects中的“死数据” 即完成了当前为动画而生的清屏方法。
那么整体步骤是怎么样呢?鼠标左键按下时清空Rect中数据并且获得鼠标的坐标(保存到Rect中),鼠标移动过程中获得第二个点(保存到Rect中)开始绘制图形Rect (绘制前过程执行动画清屏函数clear),鼠标左键弹起时候结束绘画把Rect保存到Rects中。
绘制具体代码 (伪代码)
//鼠标移动 具体绘画函数,function MouMove(mou) {if(isDraw.value===true) {if(isConver.value===false) { //不是图形变换再初始//画矩形的第二个点Rect.last.x= mou.offsetX;Rect.last.y= mou.offsetY;//画矩形if(drawWate.value==='Rect') {clear(); //进行清屏操作,同时会绘制之前已经绘制过的图形RectDraw(); //绘制矩形}}}}
为动画而生的清屏函数(伪代码)
//清屏(用于动画) 并且绘制原来的数据function clear(){// /ctx.clearRect(x,y,w,h); // (擦除一个矩形范围)ctx.value.clearRect(0,0,1200,1000);RestroedAll(); //绘制原来已经绘制好的图形}
(4)、图形变换原理
canvas上已经绘制上的图形是不能进行操作的,那么实现图形变换呢?本质还是和实现动画效果是一致的,通过绘制一个选择框矩形,通过扫描Rects中的图形数据是否在当前选择框内,如果在当前内部就通过修改对应的数据就能实现;修改的数据通过鼠标坐标来转化得到,还是很简单,明白了动画原理做这个就是顺带的。
具体实现就不细说了。
三、残留bug
一下子把完整无误的代码放出来就没意思了
这个bug是图形变换上的,应为上面提到图形变换是通过一值扫描Rects中的数据来进行图形变换的;如果这样就会在平移过程中把所有在选择框内部的图形都会进行平移操作,也就会平移到另一个图形B过程中也会影响到图形B的状态。
这里提一下解决办法,只需要在绘制选择框的时候扫描一次Rects即可,扫描后记录Rexcts中满足条件的数据,只需要操作满足条件的数据即可。
bug
四、源代码
gitee地址:HTML5: 使用vue 实现canvas画图
觉得有用、有趣欢迎评论点赞收藏!