最好的canvas鼠标画画插件drawingboard.js

JavaScript011

最好的canvas鼠标画画插件drawingboard.js,第1张

drawingboard.js其实就是一个涂鸦工具,可以用鼠标和手指(手机端)画出图案。事实上更多的可能是当签名版用,或者做为一个并不算有趣的画图板,毕竟一般人都没有手绘能力。

在我能找到的这类工具中,drawingboard.js是最好的。

无依赖。

就是这么简单。

参看 https://github.com/Leimi/drawingboard.js

chart.js是一款基于HTML5 Canvas的图表插件,chart.js的功能非常强大,它不仅提供了常见的柱形图、折线图、饼状图,而且还提供了环形图、雷达图,样式外观多样,图表的色彩搭配也比较清新。chart.js还有一个特点就是图表在初始化的时候有弹性动画特效,这也是HTML5 Canvas的一大功劳。

众所周知,canvas的api繁杂,对一般的前端er来说不太友好,加上平时一般也不会自己手写canvas,所以一般开发者对canvas的涉猎可能并不太深(我看红宝书的时候canvas是直接跳过的)。而当需要使用canvas开发一些定制化的需求时,echarts,antv系列,可能就无法满足了,这个时候或许fabric会是一个比较好的选择,fabric提供一种类似面向对象的方法来编写canvas,比原生稍微方便一些(然鹅官方文档太难看懂了)

近期的一个项目中,有这么一个需求:拖拽缩放元素并且进行连线,本来我第一反应是用antv/g6去实现的,但是需要对拖拽的元素缩放并且拖拽的容器需要放文字和图表,如果使用g6的话,缩放容器,里面的内容改变不太利索(实际是我对g6不太熟),另一个重要的问题是g6元素里面放图表的话只能放g2(而且需要单独安装插件)并且不支持诸如tooltip等等功能,简单来说只能用个阉割版的(示例: https://antv-g6.gitee.io/zh/examples/item/customNode#lineChartNode )。因此我最初想的是使用 vue-grid-layout ( github &&文档 )进行拖拽与缩放,画线使用canvas。这样做的好处是第三方组件已经把拖拽和缩放功能全都封装好了,dom元素嵌入echarts和文本缩放也相当方便(vue-echarts的autoresize,文本使用flex布局加overflow:auto),当然画线又是一个大问题,关键点就是线要和拖拽的元素接上,简而言之就是坐标计算了。考虑到画布里面还要放图(拖拽的元素连线到图上)以及要实现连线的时候鼠标移动需要不停的重绘线,最终在同事的推荐下决定使用fabric.js来实现canvas部分。然后就发现这东西用起来一言难尽...

1.官方文档

就算你英语很好看他的文档也会很别扭的,建议直接看 官方DEMO 找自己要的,不懂的百度谷歌,最后把查找文档作为补充以及检查是否有新版api和网上的古早文章不同。

2.在vue中使用

目前只能这样用

3.绘制本地图片有问题

我尝试过 fabric.Image.fromURL('xxx/xxx.png',function(){}) 以及 new Image().src 这两种发现貌似都不能放本地图片地址(类似 @/assets/... 这种),可能是我使用的方式不对,最后只剩下一种方法可用了:

这种方法首先需要在页面上放一个隐藏的img元素,结果一开始fabric还读不到只能通过 onload 事件来获取,但这样会导致画布重绘时无法执行onload,最后一个绘制图片被我写成这样了

sendToBack 方法是为了确保在后面画线的时候线能在图的上面一层显示(貌似fabric是按照先后绘制顺序排层级的,先绘制的层级最高,于是我们需要将图的层级降到最低)

可能是页面结构太复杂的缘故,上面的方法有小概率执行时图片还没加载好,导致最后画布里面其它内容都出来了结果最重要的图没了,最终我搞出来的解决办法是,在img标签上直接绑定load事件,执行load时将组件内设置的状态修改,并监听这个状态的变化来执行图片渲染到canvas画布的过程。

画图(画线除了selectable其它类似,因为我的项目需要选中线)

因为我需要点击线的时候弹出删除菜单,所以不能在初始化的时候直接 skipTargetFind: true ,我要做的是去除选中的样式和大部分功能,保留选中时能获取到选中对象,一旦这个属性设为true则会取消所有选中样式和功能,不需要在canvas对象里面再单独配置了。

第二,计算三次贝塞尔曲线的控制点,这里面用了向量运算...

网上找的检测屏幕缩放比例的方法(可以检测到系统分辨率改变)

然后在初始化fabric对象时需要重新计算宽高(canvasLayout为画布上一级的父元素)

pageZoom主要在拖动元素时计算元素与线的连接点坐标用到了,这个系统里面只要vue-grid-layout元素有改变,我就要重新计算线的起点并重绘线,通过这种办法实现了dom元素和canvas元素的绑定,听起来很low的样子,不过最后功能是都实现了。

参考文章(还有些讲fabric的api的文章找不到了...)

https://github.com/hujiulong/blog/issues/1

fabric视频教程(我还没看过,可能有些内容存在过时)

https://www.bilibili.com/video/BV1at411q7bt