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.Circle
fabric.Ellipse
fabric.Line
fabric.Polygon
fabric.Polyline
fabric.Rect
fabric.Triangle
// 复杂图形
fabric.Image
fabric.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 selection
rect.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 filter
img.filters.push(new fabric.Image.filters.Grayscale());
// apply filters and re-render canvas when done
img.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');
});
组