在实际工作中,接触到整体的一个作业批改的流程。所以对作业的批改有部分了解, 故做此fabric的使用总结,希望能够抛砖引玉,大家共同探讨
什么是Fabric.js 一个功能强大的Javascript库,使使用HTML5 canvas变得轻而易举。 Fabric.js为Canvas提供所缺少的对象模型, 交互和一整套其他不可或缺的工具
为什么要用它而不用其他的 首先,Canvas提供了一个画布的能力, 但是api不够友好。我们在pc端的批改是用的原生canvas,但应用到小程序经过调研发现并不合适。canvas.绘制简单图形其
实还可以, 不过做一些复杂的图形绘制, 编写一些复杂的效果,就不是那么方便了。所以,我们决定使用Fabric.js来开发
它主要就是用对象的 方式去编写代码。
原生: canvas 和fabric的对比
同样条件下绘制一个矩形
1 2 3 4 var canvasEl = document .getElementById('c' );var ctx = canvasEl.getContext('2d' );ctx.fillStyle =‘红色'; //在100,100点处创建20x20尺寸的矩形 ctx.fillRect(100,100,20,20);
1 2 3 4 5 6 7 8 var canvas = new fabric.Canvas('c' );var rect = new fabric.Rect({ left:100 , top:100 fill:“红色”, width:20 , Height:20 });
使用自由画笔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const drawLine = (x1, y1, x2, y2 ) => { const { ctx } = getCanvas(); ctx.lineWidth = 2 ; ctx.lineCap = 'round' ; ctx.lineJoin = 'round' ; ctx.fillStyle = 'red' ; ctx.strokeStyle = 'red' ; ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); ctx.closePath(); };
1 2 3 4 5 freeDraw ( ) { canvasCtx.isDrawingMode = true ; canvasCtx.freeDrawingBrush.color = 'red' ; canvasCtx.freeDrawingBrush.width = 2 ; };
如何使用 引入:
1 2 3 1、npm安装: npm install fabric --save 2、通过CDN引入:<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script> 3、项目中引入使用: import { fabric } from 'fabric'
创建实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 js: canvasCtx = new fabric.Canvas('my-canvas' , { enableRetinaScaling: true , perPixelTargetFind: true , skipTargetFind: true , selection: false , selectable: false }); dom: <canvas id="my-canvas" className="canvas" width=375 height=650 ></canvas>
由图可知,创建完实例后,fabric.js会构建两层 canvas 元素:lower-canvas 和 upper-canvas
lower-canvas: 只负责渲染元素
upper-canvas: 负责所有的事件处理
事件绑定 // 事件绑定
1 2 3 4 5 6 7 8 9 10 11 mouseEvent ( ) { canvasCtx.on('mouse:down' , (options ) => { TODO:获取点坐标 }); canvasCtx.on('mouse:move' , (options ) => { TODO: }); canvasCtx.on('mouse:up' , (options ) => { TODO: }; }
最新版本的Fabric已经不需要判断手动还是点击事件,兼容的Events.js能够兼容在移动端的手势操作:
根据下图对比可以看到,在不同平台下所触发的事件是不同的,所以可以开箱即用。
移动端
PC端
绘制图片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 creatImg ( ) { const imageUrl = new Image(); imageUrl.setAttribute('crossOrigin' , 'Anonymous' ); imageUrl.src = object.url; imageUrl.onload = () => { const imageBg = new fabric.Image(imageUrl, { angle: 90 , hasBorders: false , selectable: false , hasControls: false , crossOrigin: 'Anonymous' }); canvasCtx.add(imageBg); }; }
移动图片 1 2 3 4 5 6 7 8 9 handleMoveCnavas (options ) { const { x, y } = movePosition; const delta = new fabric.Point(options.x - x, options.y - y); canvasCtx.relativePan(delta); movePosition = options; }
缩放事件 下图为在移动端的示意图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 handleDoubleFinger (options ) { this .setOperationType('' ); const { clientX: finger1X, clientY: finger1Y } = options.e.targetTouches[0 ]; const { clientX: finger2X, clientY: finger2Y } = options.e.targetTouches[1 ]; const powX = (finger2X - finger1X) * (finger2X - finger1X); const powY = (finger2Y - finger1Y) * (finger2Y - finger1Y); const distance = Math .sqrt(powX + powY); let ratio = -0.05 ; if (distance > preDistance) { ratio = 0.05 ; } preDistance = distance; const x = scaleCenter.x || (Math .abs(finger1X + finger2X)) / 2 ; const y = scaleCenter.y || (Math .abs(finger1Y + finger2Y)) / 2 ; scaleCenter = { x, y }; let zoom = ratio + canvasCtx.getZoom(); zoom = Math .max(0.5 , zoom); zoom = Math .min(3 , zoom); const zoomPoint = new fabric.Point(x, y); canvasCtx.zoomToPoint(zoomPoint, zoom); }
旋转保存
总结: fabric主要是canvas基础上的一次创新,能够解决很多原生canvas处理处理起来特别麻烦的地方,在整个实例对象下,
有一个_objects数组,是用来存储在画板上的所有元素,元素的数量直接决定数组的长度,在启用撤销功能时,本质上是维护
这个数组来实现。当然,Fabric的功能远不止这些,更深一层的理解需要日后不断的积累与总结。
附录: 常用的一些API
add(object) 添加 insertAt(object,index) 添加 remove(object) 移除 forEachObject 循环遍历 getObjects() 获取所有对象 item(int) 获取子项 isEmpty() 判断是否空画板 size() 画板元素个数 fabric.util.drawDashedLine 绘制虚线 clear() 清空 renderAll() 重绘 requestRenderAll() 请求重新渲染 rendercanvas() 重绘画板? getCenter().top/left 获取中心坐标 toDatalessJSON() 画板信息序列化成最小的json toJSON() 画板信息序列化成json moveTo(object,index) 移动 setCursor() 设置手势图标 getSelectionContext()获取选中的context getSelectionElement()获取选中的元素 getActiveObject() 获取选中的对象 getActiveObjects() 获取选中的多个对象 discardActiveObject()取消当前选中对象 rotate() 设置旋转角度 setCoords() 设置坐标
fabric.js官方文档: [fabric.js官方文档]