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 元素一样直观,同时提供了专业级的图形处理能力。
全部评论