fabric.js是一个强力的JavaScript库,用以解决原生canvasAPI难以使用(只提供了基础的图像绘制API)的问题。其提供了canvas的对象模型,SVG解析器、层级交互及其他的合适工具。
比如说,在原生canvas的API中绘制一个在画布左上角的宽高分别为100的红色矩形,代码如下:
let canvas = document.createElement('canvas');let ctx = canvas.getContext('2d');ctx.fillStyle = '#FF0000';ctx.fillRect(0, 0, 100, 100);
而在fabric.js中则是如下:
let canvas = document.createElement('canvas');let fCanvas = new fabric.Canvas(canvas);let rect = new fabric.Rect({left: 0,top: 0,width: 100,height: 100,fill: '#FF0000',});fCanvas.add(rect);fCanvas.renderAll();
原生canvas的绘制旨在操作上下文(context),而fabric.js则操作对象,在fabric中,对象是一等公民。
由于对象的存在,我们在做一些复杂的效果时(比如旋转、移动)会更加得心应手。
以下是fabric.js中的基础图像。
// 基础图形fabric.Circlefabric.Ellipsefabric.Linefabric.Polygonfabric.Polylinefabric.Rectfabric.Triangle// 复杂图形fabric.Imagefabric.Path// 对象使用let dCanvas = document.createElement('canvas');let canvas = new fabric.Canvas(dCanvas);let rect = new fabric.Rect({width: 100,height: 100,left: 10,top: 10,fill: '#FF0000',});canvas.add(rect);canvas.renderAll();// 对象控制rect.set({left: 20, top: 20, angle: 45});
通过 get方法可以获取可设置的属性,然后通过 set进行设置。
通过也提供了多个get*的方法,比如getWidth(),getScaleX()
大多数的对象都继承自fabric.Object
在渲染时,所有的对象会被渲染到一个canvas被fabric.Canvas包装的canvas中,而对象操作则会在另一张canvas中,如下图所示。

var canvas = new fabric.Canvas('c');...canvas.selection = false; // disable group selectionrect.set('selectable', false); // make object unselectable
以上代码可以设置canvas是否可以组选及对象是否可选中。
如果完全不想要交互功能,则可以使用fabric.StaticCanvas替代fabric.Canvas
fabric.js内置了一套动画系统。
rect.animate('angle', 45, {onChange: canvas.renderAll.bind(canvas)});rect.animate('angle', '+=45', {onChange: canvas.renderAll.bind(canvas)});
每个对象拥有自己的属性,而canvas仅仅作为渲染管理,所有在动画的过程中,对象只会根据时间自动进行属性更新,不会熏染画面,我们需要重新渲染画布以达到动画的目的。但是让每个对象都去重新渲染并不是一个好的方案(出于性能考虑),我们可以对canvas进行统一的管理,通过requestAnimationFrame 或是其他的动画机制来进行渲染。
图片滤镜
fabric.js自带部分滤镜效果,同时支持自定义滤镜。
fabric.Image.fromURL('pug.jpg', function(img) {// add filterimg.filters.push(new fabric.Image.filters.Grayscale());// apply filters and re-render canvas when doneimg.applyFilters();// add image onto canvas (it also re-render the canvas)canvas.add(img);});
以下是自定义滤镜的使用
fabric.Image.filters.Redify = fabric.util.createClass(fabric.Image.filters.BaseFilter, {type: 'Redify',/*** Fragment source for the redify program*/fragmentSource: 'precision highp float;\n' +'uniform sampler2D uTexture;\n' +'varying vec2 vTexCoord;\n' +'void main() {\n' +'vec4 color = texture2D(uTexture, vTexCoord);\n' +'color.g = 0;\n' +'color.b = 0;\n' +'gl_FragColor = color;\n' +'}',applyTo2d: function(options) {var imageData = options.imageData,data = imageData.data, i, len = data.length;for (i = 0; i < len; i += 4) {data[i + 1] = 0;data[i + 2] = 0;}}});fabric.Image.filters.Redify.fromObject = fabric.Image.filters.BaseFilter.fromObject;
文本
fabric.js提供了文本操作,可以和其他对象一样进行属性控制。(fontSize, fontFamily, fontWeight, textDecoration, shadow, fontStyle, stroke, strokeWidth, textAlign, lineHeight, textBackgroundColor)
var text = new fabric.Text('hello world', { left: 100, top: 100 });canvas.add(text);
事件
fabric.js提供了广泛的事件系统,包括低级的鼠标事件及高级的对象事件,on添加事件,off移除事件。
canvas.on('mouse:down', function(options) {console.log(options.e.clientX, options.e.clientY);if (options.target) {console.log(options.target.type);}});
以上代码是给canvas添加mouseDown事件,输出点击坐标,回调中的options含有两个属性(还有其他的),e是原生event,target是当前点击的对象。除了此事件外还有其他事件:mouse:move,mouse:up,after:render,before:selection:cleared、selection:created、selection:cleared,object:modified,object:selected,object:moving,object:scaling,object:rotating,object:added,object:removed等。
同时,事件不仅可以添加到画布上,还可以添加到对象上。比如:
var rect = new fabric.Rect({ width: 100, height: 50, fill: 'green' });rect.on('selected', function() {console.log('selected a rectangle');});var circle = new fabric.Circle({ radius: 75, fill: 'blue' });circle.on('selected', function() {console.log('selected a circle');});
组
