fabric.js是一个强力的JavaScript库,用以解决原生canvasAPI难以使用(只提供了基础的图像绘制API)的问题。其提供了canvas的对象模型,SVG解析器、层级交互及其他的合适工具。
    比如说,在原生canvas的API中绘制一个在画布左上角的宽高分别为100的红色矩形,代码如下:

    1. let canvas = document.createElement('canvas');
    2. let ctx = canvas.getContext('2d');
    3. ctx.fillStyle = '#FF0000';
    4. ctx.fillRect(0, 0, 100, 100);

    而在fabric.js中则是如下:

    1. let canvas = document.createElement('canvas');
    2. let fCanvas = new fabric.Canvas(canvas);
    3. let rect = new fabric.Rect({
    4. left: 0,
    5. top: 0,
    6. width: 100,
    7. height: 100,
    8. fill: '#FF0000',
    9. });
    10. fCanvas.add(rect);
    11. fCanvas.renderAll();

    原生canvas的绘制旨在操作上下文(context),而fabric.js则操作对象,在fabric中,对象是一等公民。
    由于对象的存在,我们在做一些复杂的效果时(比如旋转、移动)会更加得心应手。

    以下是fabric.js中的基础图像。

    1. // 基础图形
    2. fabric.Circle
    3. fabric.Ellipse
    4. fabric.Line
    5. fabric.Polygon
    6. fabric.Polyline
    7. fabric.Rect
    8. fabric.Triangle
    9. // 复杂图形
    10. fabric.Image
    11. fabric.Path
    12. // 对象使用
    13. let dCanvas = document.createElement('canvas');
    14. let canvas = new fabric.Canvas(dCanvas);
    15. let rect = new fabric.Rect({
    16. width: 100,
    17. height: 100,
    18. left: 10,
    19. top: 10,
    20. fill: '#FF0000',
    21. });
    22. canvas.add(rect);
    23. canvas.renderAll();
    24. // 对象控制
    25. rect.set({left: 20, top: 20, angle: 45});

    通过 get方法可以获取可设置的属性,然后通过 set进行设置。
    通过也提供了多个get*的方法,比如getWidth()getScaleX()
    大多数的对象都继承自fabric.Object

    在渲染时,所有的对象会被渲染到一个canvas被fabric.Canvas包装的canvas中,而对象操作则会在另一张canvas中,如下图所示。
    7.png8.png

    1. var canvas = new fabric.Canvas('c');
    2. ...
    3. canvas.selection = false; // disable group selection
    4. rect.set('selectable', false); // make object unselectable

    以上代码可以设置canvas是否可以组选及对象是否可选中。
    如果完全不想要交互功能,则可以使用fabric.StaticCanvas替代fabric.Canvas


    fabric.js内置了一套动画系统。

    1. rect.animate('angle', 45, {
    2. onChange: canvas.renderAll.bind(canvas)
    3. });
    4. rect.animate('angle', '+=45', {
    5. onChange: canvas.renderAll.bind(canvas)
    6. });

    每个对象拥有自己的属性,而canvas仅仅作为渲染管理,所有在动画的过程中,对象只会根据时间自动进行属性更新,不会熏染画面,我们需要重新渲染画布以达到动画的目的。但是让每个对象都去重新渲染并不是一个好的方案(出于性能考虑),我们可以对canvas进行统一的管理,通过requestAnimationFrame 或是其他的动画机制来进行渲染。

    图片滤镜
    fabric.js自带部分滤镜效果,同时支持自定义滤镜。

    1. fabric.Image.fromURL('pug.jpg', function(img) {
    2. // add filter
    3. img.filters.push(new fabric.Image.filters.Grayscale());
    4. // apply filters and re-render canvas when done
    5. img.applyFilters();
    6. // add image onto canvas (it also re-render the canvas)
    7. canvas.add(img);
    8. });

    以下是自定义滤镜的使用

    1. fabric.Image.filters.Redify = fabric.util.createClass(fabric.Image.filters.BaseFilter, {
    2. type: 'Redify',
    3. /**
    4. * Fragment source for the redify program
    5. */
    6. fragmentSource: 'precision highp float;\n' +
    7. 'uniform sampler2D uTexture;\n' +
    8. 'varying vec2 vTexCoord;\n' +
    9. 'void main() {\n' +
    10. 'vec4 color = texture2D(uTexture, vTexCoord);\n' +
    11. 'color.g = 0;\n' +
    12. 'color.b = 0;\n' +
    13. 'gl_FragColor = color;\n' +
    14. '}',
    15. applyTo2d: function(options) {
    16. var imageData = options.imageData,
    17. data = imageData.data, i, len = data.length;
    18. for (i = 0; i < len; i += 4) {
    19. data[i + 1] = 0;
    20. data[i + 2] = 0;
    21. }
    22. }
    23. });
    24. fabric.Image.filters.Redify.fromObject = fabric.Image.filters.BaseFilter.fromObject;

    文本
    fabric.js提供了文本操作,可以和其他对象一样进行属性控制。(fontSize, fontFamily, fontWeight, textDecoration, shadow, fontStyle, stroke, strokeWidth, textAlign, lineHeight, textBackgroundColor)

    1. var text = new fabric.Text('hello world', { left: 100, top: 100 });
    2. canvas.add(text);

    事件
    fabric.js提供了广泛的事件系统,包括低级的鼠标事件及高级的对象事件,on添加事件,off移除事件。

    1. canvas.on('mouse:down', function(options) {
    2. console.log(options.e.clientX, options.e.clientY);
    3. if (options.target) {
    4. console.log(options.target.type);
    5. }
    6. });

    以上代码是给canvas添加mouseDown事件,输出点击坐标,回调中的options含有两个属性(还有其他的),e是原生event,target是当前点击的对象。除了此事件外还有其他事件:mouse:movemouse:upafter:renderbefore:selection:clearedselection:createdselection:clearedobject:modifiedobject:selectedobject:movingobject:scalingobject:rotatingobject:addedobject:removed等。
    同时,事件不仅可以添加到画布上,还可以添加到对象上。比如:

    1. var rect = new fabric.Rect({ width: 100, height: 50, fill: 'green' });
    2. rect.on('selected', function() {
    3. console.log('selected a rectangle');
    4. });
    5. var circle = new fabric.Circle({ radius: 75, fill: 'blue' });
    6. circle.on('selected', function() {
    7. console.log('selected a circle');
    8. });