canvas实现图片编辑(canvas实现图片标记)
前言
由于业务需求 ,需要有一个图片标记功能 ,其实就是对图片画框画线做标记,类似微信的图片编辑
但是需要存下标记图及其标记的具体数据, 。功能其实很简单 ,但刚开始的时候也是费了一些功夫的 。我将原项目中该功能抽离出来单独写了一个demo ,作为记录 ,同时你们在开发过程中有类似需求的话也可以参考一下该思路 ,其中有不足之处还请指出来。实现目标
1 、定点缩放 。
2 、图片拖拽 。
3、图片中绘制点 、直线 、矩形 、圆形 、多边形 。
4 、上传原图 。
5 、下载标注图 。
6 、记录标记数据 。具体效果
这是在线浏览地址 。
这是源码地址 。实现思路
项目是纯原生canvas实现的 ,没使用任何其他插件 。由于canvas没有图层的概念 ,实现切换不同的绘制模式时有一点麻烦。具体方案是:分别单独存下每次绘制的数据 ,再将该数据添加到一个大列表中(如下图中的canvasData) ,每次绘制图形时都需要重绘该大列表 ,若需要操作绘制的图形,则变动大列表中对应的数据后重绘即可 。
具体逻辑
1 、绑定事件 。先添加画布canvas ,并指定画布尺寸与绑定各种事件:滚轮事件(mousewheel) 、右键事件(contextmenu)、鼠标按下事件(mousedown) 、鼠标松开事件(mouseup) 、鼠标移动事件(mousemove)、双击事件(dblclick)。
2 、绘制模式 。该功能有五种绘图模式:点模式 、直线模式、矩形模式 、多边形模式 、圆形模式 。点模式最简单 ,在鼠标松开事件中绘制点,然后获取到坐标 ,最后将数据添加到大列表中。
其中canvas绘制点的方法如下 ,其实就是利用ctx.arc绘制一个实心圆,arc四个参数分别为圆心坐标x 、y 、半径 、起始角度 、终止角度 。
直线模式的绘制是在鼠标移动事件中 ,移动时不停的调用ctx.clearRect清除绘制的图形 ,然后再不停的绘制大列表的数据 ,鼠标松开后将再将直线绘图数据添加到大列表中 ,从而实现拖拽画线的效果 。canvas绘制直线的方法如下 ,其中最主要的便是ctx.lineTo方法 。
矩形模式的绘制与直线绘制一样 ,也是放在鼠标移动事件中的 。拖拽即可绘制出矩形 。具体canvas绘制矩形的方法如下 ,其中ctx.strokeRect方法四个参数分别为矩形左上角的x 、y坐标 ,矩形长度 、矩形宽度 。
多边形绘制模式比较麻烦一点 。我设计的操作模式是 ,右键依次点击多边形的顶点,最后需要闭合时双击左键即可完成绘制 ,闭合多边形 ,将多边形数据添加到大列表中 。这样只需判断每次点击绘制时是否闭合即可,双击事件处理如下 。
圆形模式绘制的绘制与点的绘制类似 ,也是使用ctx.arc。不同的是圆需要计算半径 ,在鼠标松开的一瞬间记录下坐标,使用该坐标平方后再开根即可计算出半径 。具体绘制方法如下 。
3 、定点缩放。需要保证鼠标中心位置与图片比例不能改变 ,该功能是绑定鼠标滚动事件的 ,每次缩放时需要重新计算比例与坐标 ,重绘大列表的数据 ,这是滚动事件的处理 ,需要注意事件中wheelDelta值的正负 。
这是改变画布的方法 ,画布尺寸是通过缩放倍数与原图尺寸控制的 ,画布位置是通过旧位置加偏移量来控制的 。需要限制缩放倍数的话控制maxZoom与minZoon即可。
4、图片拖拽 。该功能的实现则比较简单 ,点击左键后打开限制拖拽的状态 ,记录拖拽偏移量 。
鼠标移动时,实时改变画布的top与left即可(这里是通过position: absolute;定位的) 。
5 、上传原图 。这里的上传并不是上传到服务器中 ,而是利用input type="file"选取文件到浏览器中处理 ,需要限制为只选取图片,使用accept="image/jpeg"属性 。
其中上传的方法如下 ,需要限制文件大小 ,然后通过createObjectURL获取到url(该url比较特殊,只在当前dom页面中有效) 。
最后通过loadBgImg方法返回一个img ,页面中即可使用该图片 ,从而实现“上传 ” 。
6 、下载标注图 。值得注意的是为防止标记错位 ,需要下载前需要将图片尺寸位置还原 ,然后再获取页面中canvas的DOM ,然后通过toDataURL获取到base64 。
将该base64生成转化为Blob ,然后创建事件 ,使用a标签下载 ,路径仍然使用createObjectURL获取。
7、记录标记数据 。记录标记数据的好处是 ,将来若需要单独编辑每个标记,则可以直接改变记录下的数据 ,然后重绘该数据即可 。记录数据的逻辑是写在鼠标松开事件中的 ,每次绘制完标记后都需要将绘图数据push到大列表中。结语
在开发过程中我还是踩了很多坑的,文章中记录的只是很少的一部分 。还是建议看文章开头的项目源码链接 ,源码中我写了大量详细的注释 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!