pixi.js
d3.js
tree.js
zrender.js
具体可以到GitHub平台去下载或者了解它们。
众所周知,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
<canvas>是HTML 5 新增的元素,可用于通过使用JavaScript中的脚本来绘制图形
<canvas>元素只是创造了一个固定大小的画布,要想在它上面绘制内容,我们需要找到它的渲染上下文
<canvas>元素有一个getContex()方法,这个方法是用来获取渲染上下文和它的绘画功能