快速构建一个完整的图片标注功能
需求分析
页面中显示需要标注的图片,鼠标绘制矩形进行标注(考虑到实际情况,可能还有多边形、圆形等等多种形状)。最后可以拿到标注的内容位置信息、标注信息等并且回显所有标注内容。在图片上进行绘制,首先想到的是用canvas,canvas强大的功能能让我们在图片上为所欲为。但是原生的canvas API众多且繁杂,上手不易,所以最好使用成熟的canvas框架来实现。
使用ailabel
ailabel只看说明这个框架好像完全满足我们的需求,但是可惜源码地址已经不存在了,文档也无法访问。不过好在网上有人fork源码库,我们可以直接下载后查看文档和demo。
好,先安装依赖nmp install
,然后打开demo/index.html
文件,就可以看到demo了。
但是但是但是啊,项目报错了,不管是绘制什么图形,鼠标松开后都不显示图形。F12查看发现一堆报错信息,除了第一条信息外全都是没有EventEmitter导致的。看来是没有事件触发与事件监听器功能导致绘制事件无法执行。
通过package.json可以知道ailabel使用了events库来作为事件机制,应该是这个库没起作用。幸运的是ailabel是支持手动编译的,也就是说我们可以修改它的源码。替换一个跟events库相同功能的库tiny-mitter(我们项目中正在使用的事件发射器库)。
运行npm run build
重新打包,更新demo的引用文件,再次运行demo。图片已显示,标注也能正常显示,控制台也没有报错信息,一切OK。
通过一系列验证测试基本可以认定该框架满足需求,可以使用。
ailabel确实可以满足大部分图片标注功能,但是它可定制行、可扩展性很小,而且源码库不在说明作者已经不维护,这就需求我们手动维护。
下面介绍一种完全定制化标注的基础实现。
使用fabric
fabricjs是一个基于canvas的强大的框架,提供一种类似面向对象的方法来编写canvas,在原生canvas之上提供了交互式对象模型,通过简洁的API就可以在画布上进行丰富的操作
关于fabricjs的介绍和使用请参考 fabricjs从精通到,我们重点介绍标注画框的交互。
绘制标注
fabric提供了一系列的事件帮助我们来很好的对画布进行各种操作,标注画框主要用到的是下图中的mouse:down
:画笔落下;mouse:move
:画框;mouse:up
画笔抬起事件
下面以绘制矩形为例进行说明
1 | var fabCanvas = new fabric.Canvas(id,{xxxx}) |
其他形状如圆形、线段、多边形等实现逻辑都是大同小异,fabric都是支持对应形状的绘制的。
调整标注
如果初始化设置画布不可选,要先把画布设为可选才能选中标注
1 | fabCanvas.set({ |
Copy
如果要修改标注的默认选中样式,可以修改标注的对应参数
1 | fabCanvas.on('selection:created': (e)=>{ |
调整画框主要用到上述的object:moving
:对象移动;object:modified
:对象调整;
1 | fabCanvas.on('object:modified':(e)=> { |
选中标注
在新建形状中监听select
事件,可以抛出对应事件
1 | rect.on('selected',(e)=>{ |
删除标注
直接调用fabric的remove事件
1 | fabCanvas.remove(rect) |
清空所有画框
1 | clearAllMark(){ |
放大缩小
1 | fabCanvas.setZoom(10) |
以上交互已经包含了绝大部分的图片交互,只是有点碎。
总结
ailabel
提供了一套完整的打点,绘制矩形、多边形等各种形状的标注框架。简单易用功能完善,但是可扩展性差而且需要自行维护(作者已经删库)
fabricjs
是基于canvas类似面向对象的框架。可以绘制什么图形,可扩展和定制型强,但是需要手动监听鼠标事件自己实现绘制标注逻辑,时间成本高