Fabric 是基于 HTML5 canvas 的图形库,通过操作对象的属性来操作 canvas (叫 object model),已经提供了一些基本的图元,如 Rect, Circle, Ellipse, Line, Polygon, Image, SVG, Text, Textbox, 阴影等,支持动画、拖动放大缩小旋转等,还支持自由绘制,能够序列化为字符串方便保存,需要的时候再把字符串反序列化为 fabric.Canvas 对象。
Fabric.js is a powerful and simple Javascript HTML5 canvas library. Fabric provides interactive object model on top of canvas element. Fabric also has SVG-to-canvas (and canvas-to-SVG) parser.
下面列举一些可能会常用到的知识点:
全局设置默认值: fabric.Object.prototype.transparentCorners = false
(cornerSize: 7)
导出时包含指定 / 自定义属性: canvas.toJSON(['name', 'lockScalingY']
,默认很多属性都没有到处,根据自己的需要在这里指定
设置选中 item 的属性: canvas.getActiveObject().set("fontFamily", 'Monaco')
修改整个 canvas 的鼠标: canvas.defaultCursor = 'move'
<canvas width="100" height="100">
的大小被 Canvas 中指定的值覆盖: new fabric.Canvas('c', { width: 600, height: 600 })
控制点 controls 指的是选中图形后在图形边框上出现的 8 个用来控制图形大小的小方框,名字为 tl, tr, br, bl, ml, mt, mr, mb
canvas.renderAll()
会立即重绘,canvas.requestRenderAll()
则是把重绘的命令放到事件队列里,如果准备放入时已经存在则丢弃,不重复放入队列中
常用属性: Well, as you would expect there are those related to
positioning: left, top
dimension: width, height
rendering: fill, opacity, stroke, strokeWidth
scaling and rotation: scaleX, scaleY, angle
flipping: flipX, flipY
skewing: skewX, skewY
在 Fabric Demos 里有很多例子,对学习 Fabric 非常有帮助。
多行字符串 多行字符串 Textbox 的文档里介绍说只能拖动修改宽度,高度不能拖动修改,而是根据文字的多少来进行计算的,可能是有 Bug,目前拖动能够修改高度,可以设置 lockScalingY 为 true 解决这个问题。
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 37 38 39 40 41 42 43 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <style > canvas { border : 1px solid #ccc ; } </style > </head > <body > <canvas id ="c" width ="400" height ="400" > </canvas > <br > <button > Change</button > <script src ="lib/fabric.min.js" > </script > <script > let canvas = new fabric.Canvas('c' , { width : 600 , height : 600 }); let textbox = new fabric.Textbox('HTML canvas 的框架很多, 比如 Three.js 是有名的 3D 框架' , { left : 10 , top : 30 , width : 200 , fontSize : 14 , lineHeight : 1.5 , textAlign : 'left' , splitByGrapheme : true , lockScalingY : true , }); canvas.add(textbox); document .querySelector('button' ).addEventListener('click' , () => { textbox.set('fontSize' , 20 ); canvas.renderAll(); }); </script > </body > </html >
加载图片 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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <style > canvas { border : 1px solid #ccc ; } </style > </head > <body > <canvas id ="c" width ="400" height ="400" > </canvas > <br > <script src ="lib/fabric.min.js" > </script > <script > let canvas = new fabric.Canvas('c' ); fabric.Image.fromURL('img/avatar.jpg' , img => { if (img.width > 100 ) { img.scale(100 / img.width); } canvas.add(img); }); </script > </body > </html >
坐标原点 图元的默认坐标原点 originX and originY 为左上角,可以指定为图元中心 center。
1 2 3 4 5 6 7 8 9 10 let rect = new fabric.Rect({ left : 0 , top : 0 , width : 100 , height : 100 , fill : 'red' , angle : 45 , originX : 'center' , originY : 'center' , });
设置背景图 canvas.setBackgroundImage('img/avatar.jpg', canvas.renderAll.bind(canvas))
不会拉伸图片铺满整个 canvas,使用下面的代码实现背景图平铺满 canvas。
1 2 3 4 5 6 7 8 9 10 11 12 fabric.Image.fromURL('img/avatar.jpg' , function (img ) { img.scaleToWidth(canvas.width); img.scaleToHeight(canvas.height); canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); });
修改 canvas 的大小,需要重新适配背景图:
1 2 3 4 5 6 7 8 9 10 11 document .querySelector('#button-size' ).addEventListener('click' , () => { canvas.setWidth(300 ); canvas.setHeight(300 ); let img = canvas.backgroundImage; img.scaleToWidth(canvas.width); img.scaleToHeight(canvas.height); canvas.requestRenderAll(); });
Canvas 生成图片 可以不需要 <canvas>
,直接操作 fabric.Canvas 然后生成图片。
1 <img style="max-width: 100px">
1 2 3 4 5 6 7 8 9 10 11 let canvas = new fabric.StaticCanvas(null , { width : 300 , height : 300 });canvas.add(rect); document .querySelector('img' ).src = canvas.toDataURL('png' );canvas.loadFromJSON(canvasJson, () => { document .querySelector('img' ).src = canvas.toDataURL('png' ); });
图片导出的路径 使用 canvas.toJSON()
序列化时,图片的路径为包含了协议、域名、端口的绝对路径,如 http://127.0.0.1/img/avatar.jpg ,有的时候需要其他格式的路径,例如转为 / 开头的绝对路径,可以重写 Image 的 toObject 函数实现:
1 2 3 4 5 6 7 8 fabric.Image.prototype.toObject = (function (toObject ) { return function ( ) { return fabric.util.object.extend(toObject.call(this ), { src : this .getSrc().replace(window .location.origin, '' ) }); }; })(fabric.Image.prototype.toObject);