Fabric.js 是一个功能强大的 HTML5 Canvas 库,它通过面向对象的方式简化了 Canvas 操作,为开发者提供了丰富的图形操作功能和直观的 API 接口。
 
2. 对象继承体系
fabric.Object:所有图形基类
fabric.Rect:矩形
fabric.Circle:圆形
fabric.Triangle:三角形
fabric.Text:文本
fabric.Image:图像
fabric.Path:路径
fabric.Group:对象组
fabric.ActiveSelection:活动选择组
 
// 创建画布实例
const canvas = new fabric.Canvas('canvas-id', {
 width: 800,       // 画布宽度
 height: 600,      // 画布高度
 backgroundColor: '#f5f5f5',  // 背景色
 selection: true,  // 是否启用选择
 preserveObjectStacking: true // 保持对象堆叠顺序
});
 
// 创建矩形
const rect = new fabric.Rect({
 left: 100,
 top: 100,
 width: 200,
 height: 100,
 fill: 'red',
 angle: 45,
 stroke: 'black',
 strokeWidth: 2
});
// 创建圆形
const circle = new fabric.Circle({
 radius: 50,
 fill: 'blue',
 left: 300,
 top: 200
});
// 添加对象到画布
canvas.add(rect, circle);
canvas.renderAll(); // 渲染更新
 
// 对象选择事件
canvas.on('selection:created', (e) => {
 console.log('选中对象:', e.selected);
});
// 对象移动事件
canvas.on('object:moving', (e) => {
 console.log('移动对象:', e.target);
});
// 对象缩放事件
canvas.on('object:scaling', (e) => {
 console.log('缩放对象:', e.target);
});
 
// 启用自由绘制
canvas.isDrawingMode = true;
// 配置画笔
canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
canvas.freeDrawingBrush.width = 5;
canvas.freeDrawingBrush.color = '#000000';
// 绘制完成事件
canvas.on('path:created', (e) => {
 console.log('绘制路径:', e.path);
});
 
// 简单动画
rect.animate('angle', 360, {
 duration: 1000,
 onChange: canvas.renderAll.bind(canvas),
 easing: fabric.util.ease.easeInOutQuad
});
// 复杂动画
fabric.util.animate({
 startValue: 0,
 endValue: 100,
 duration: 500,
 onChange: (value) => {
   circle.set('left', value);
   canvas.renderAll();
 },
 onComplete: () => {
   console.log('动画完成');
 }
});
 
// 创建图像对象
fabric.Image.fromURL('image.jpg', (img) => {
 // 添加滤镜
 img.filters.push(
   new fabric.Image.filters.Grayscale(),
   new fabric.Image.filters.Brightness({ brightness: 0.2 })
 );
 img.applyFilters();
 canvas.add(img);
});
 
// 批量操作时暂停渲染
canvas.renderOnAddRemove = false;
// 执行多个操作...
canvas.renderOnAddRemove = true;
canvas.renderAll();
// 使用 requestAnimationFrame
function animate() {
 requestAnimationFrame(() => {
   // 更新对象属性
   canvas.renderAll();
   animate();
 });
}
 
// 移除对象时彻底销毁
canvas.remove(object);
object = null;
// 清理画布
canvas.dispose();
 
// 使用对象缓存
object.set({
 objectCaching: true,
 dirty: false
});
// 按需渲染
canvas.onlyRenderOnRequest = true;
canvas.requestRenderAll();
 
// 创建自定义箭头对象
fabric.Arrow = fabric.util.createClass(fabric.Line, {
 type: 'arrow',
 
 initialize: function(points, options) {
   options || (options = {});
   this.callSuper('initialize', points, options);
 },
 
 _render: function(ctx) {
   this.callSuper('_render', ctx);
   
   // 绘制箭头头部
   ctx.save();
   const xDiff = this.x2 - this.x1;
   const yDiff = this.y2 - this.y1;
   const angle = Math.atan2(yDiff, xDiff);
   
   ctx.translate(this.x2, this.y2);
   ctx.rotate(angle);
   ctx.beginPath();
   ctx.moveTo(0, 0);
   ctx.lineTo(-10, -5);
   ctx.lineTo(-10, 5);
   ctx.closePath();
   ctx.fillStyle = this.stroke;
   ctx.fill();
   ctx.restore();
 }
});
// 添加到画布
const arrow = new fabric.Arrow([50, 50, 200, 200], {
 stroke: 'red',
 strokeWidth: 3
});
canvas.add(arrow);
 
// 添加自定义控制点
fabric.Object.prototype.controls.customControl = new fabric.Control({
 x: 0.5,
 y: -0.5,
 actionHandler: function(eventData, transform, x, y) {
   // 自定义处理逻辑
 },
 render: function(ctx, left, top, styleOverride, fabricObject) {
   // 自定义渲染
 },
 cornerSize: 15
});
 
// 工具栏功能实现
document.getElementById('btn-rect').addEventListener('click', () => {
 const rect = new fabric.Rect({
   width: 100,
   height: 100,
   fill: '#ff0000'
 });
 canvas.add(rect);
});
// 属性面板绑定
document.getElementById('color-picker').addEventListener('change', (e) => {
 const active = canvas.getActiveObject();
 if (active) {
   active.set('fill', e.target.value);
   canvas.renderAll();
 }
});
 
// 标注工具
let drawingMode = 'rect';
let currentAnnotation = null;
canvas.on('mouse:down', (o) => {
 if (drawingMode === 'rect') {
   currentAnnotation = new fabric.Rect({
     left: o.absolutePointer.x,
     top: o.absolutePointer.y,
     width: 0,
     height: 0,
     fill: 'rgba(255,0,0,0.2)',
     stroke: 'red',
     strokeWidth: 1,
     selectable: true
   });
   canvas.add(currentAnnotation);
 }
});
canvas.on('mouse:move', (o) => {
 if (currentAnnotation) {
   currentAnnotation.set({
     width: o.absolutePointer.x - currentAnnotation.left,
     height: o.absolutePointer.y - currentAnnotation.top
   });
   canvas.renderAll();
 }
});
 
// 连接线实现
class Connector extends fabric.Line {
 constructor(from, to, options) {
   super([from.left, from.top, to.left, to.top], options);
   this.from = from;
   this.to = to;
   this.set({
     stroke: '#666',
     strokeWidth: 2,
     selectable: false,
     evented: false
   });
 }
 
 update() {
   this.set({
     x1: this.from.left + this.from.width/2,
     y1: this.from.top + this.from.height/2,
     x2: this.to.left + this.to.width/2,
     y2: this.to.top + this.to.height/2
   });
 }
}
// 自动更新连接线
canvas.on('object:moving', () => {
 canvas.forEachObject(obj => {
   if (obj instanceof Connector) {
     obj.update();
   }
 });
});
 
Fabric.js 是一个功能全面且灵活的 Canvas 库,通过其丰富的 API 和事件系统,开发者可以构建从简单的图形编辑器到复杂的可视化应用的各类 Canvas 应用。它的面向对象设计模式使得操作 Canvas 元素就像操作 DOM 元素一样直观,同时提供了专业级的图形处理能力。

全部评论