前端开源canvas库Fabric的基本绘制功能

22人浏览 / 0人评论 / 添加收藏

Fabric.js 是一个功能强大的 HTML5 Canvas 库,它通过面向对象的方式简化了 Canvas 操作,为开发者提供了丰富的图形操作功能和直观的 API 接口。

一、核心特性

1. 基础能力
完整的对象模型:将画布元素抽象为对象(矩形、圆形、路径等)
交互式操作:内置支持拖拽、旋转、缩放等交互
丰富的图形类型:支持路径、图像、文本、组等
动画系统:提供流畅的动画支持
滤镜效果:内置多种图像滤镜
序列化/反序列化:支持 JSON 导入导出
2. 高级功能
自由绘制:铅笔、喷枪等绘画工具
SVG 支持:解析和渲染 SVG
事件系统:完善的鼠标/触摸事件
裁剪和蒙版:支持复杂裁剪操作
自定义扩展:可扩展新的对象类型和功能
 

二、基本架构

1. 核心类结构

2. 对象继承体系
fabric.Object:所有图形基类
fabric.Rect:矩形
fabric.Circle:圆形
fabric.Triangle:三角形
fabric.Text:文本
fabric.Image:图像
fabric.Path:路径
fabric.Group:对象组
fabric.ActiveSelection:活动选择组
 

三、核心 API 详解

1. 画布初始化

// 创建画布实例
const canvas = new fabric.Canvas('canvas-id', {
 width: 800,       // 画布宽度
 height: 600,      // 画布高度
 backgroundColor: '#f5f5f5',  // 背景色
 selection: true,  // 是否启用选择
 preserveObjectStacking: true // 保持对象堆叠顺序
});
 

2. 基本图形创建

// 创建矩形
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(); // 渲染更新
 

3. 交互功能

// 对象选择事件
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);
});
 

四、高级功能实现

1. 自由绘制实现

// 启用自由绘制
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);
});
 

2. 动画系统

// 简单动画
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('动画完成');
 }
});
 

3. 滤镜应用

// 创建图像对象
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);
});
 

五、性能优化技巧

1. 渲染优化

// 批量操作时暂停渲染
canvas.renderOnAddRemove = false;
// 执行多个操作...
canvas.renderOnAddRemove = true;
canvas.renderAll();

// 使用 requestAnimationFrame
function animate() {
 requestAnimationFrame(() => {
   // 更新对象属性
   canvas.renderAll();
   animate();
 });
}
 

2. 内存管理

// 移除对象时彻底销毁
canvas.remove(object);
object = null;

// 清理画布
canvas.dispose();
 

3. 大数据量优化

// 使用对象缓存
object.set({
 objectCaching: true,
 dirty: false
});

// 按需渲染
canvas.onlyRenderOnRequest = true;
canvas.requestRenderAll();
 

六、扩展开发

1. 自定义对象

// 创建自定义箭头对象
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);
 

2. 自定义控件

// 添加自定义控制点
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
});
 

七、实际应用场景

1. 图形编辑器实现

// 工具栏功能实现
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();
 }
});
 

2. 图像标注系统

// 标注工具
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();
 }
});
 

3. 流程图设计器

// 连接线实现
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 元素一样直观,同时提供了专业级的图形处理能力。


全部评论