Fabric.js 入门教程:扩展自定义对象的完整实践(V6)

  • 📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!
  • 📢本文作者:由webmote 原创
  • 📢作者格言:新的征程,用爱发电,去丈量人心,是否能达到人机合一?

Fabric.js 入门教程:扩展自定义对象的完整实践

Fabric.js 是一个功能强大的 HTML5 Canvas 库,用于构建交互式、可编辑的图形应用程序。本篇文章将通过逐步扩展 Fabric.js 的对象,创建一个名为 ComNode 的自定义节点组件,帮助读者从入门到精通 Fabric.js 的对象扩展功能。

这里有教程,可以随时收藏翻阅,一个V6版本的中文档手册,目前目录如下,大家可以点击 FabricJS.cc 访问, 下面全部代码可在 FabricJs playground 内访问。


一、基础概念与准备

Fabric.js 提供了一个基础框架,可以扩展它的内置对象,如 Rect(矩形)、Circle(圆形)等。在这篇文章中,我们将基于 Rect 扩展一个新的对象,ComNode,它包含以下功能:

  1. 额外的 icon 属性。
  2. 支持自定义控制点(Anchors)。
  3. 可序列化和反序列化。

环境准备

确保你已经安装 Fabric.js:

bash 复制代码
npm install fabric

在代码中引入 Fabric.js 和基础模块:

typescript 复制代码
import {
  classRegistry,
  Control,
  ObjectEvents,
  Rect,
  RectProps,
  SerializedRectProps,
  TClassProperties,
  TOptions,
} from 'fabric';

二、构造自定义对象 ComNode

1. 定义对象的属性

Fabric.js 使用属性作为核心控制点。我们将添加 icon 属性:

typescript 复制代码
interface UniqueComNodeProps {
  icon: string; // 自定义属性
}

同时,定义序列化所需的扩展接口:

typescript 复制代码
export interface SerializedComNodeProps
  extends SerializedRectProps,
    UniqueComNodeProps {}

2. 设置默认值

通过静态属性为新对象设定默认值:

typescript 复制代码
export const comNodeDefaultValues: Partial<TClassProperties<ComNode>> = {
  icon: '',
};

3. 创建 ComNode 类

接下来,创建一个继承自 Rect 的类:

typescript 复制代码
export class ComNode<
    Props extends TOptions<ComNodeProps> = Partial<ComNodeProps>,
    SProps extends SerializedComNodeProps = SerializedComNodeProps,
    EventSpec extends ObjectEvents = ObjectEvents
  >
  extends Rect<Props, SProps, EventSpec>
  implements RectProps {
  
  declare icon: string;

  static type = 'ComNode';
  static cacheProperties = [...Rect.cacheProperties, 'icon'];

  constructor(options?: Props) {
    super();
    Object.assign(
      this,
      ComNode.ownDefaults,
      (this.constructor as typeof ComNode).createAnchors()
    );
    this.setOptions(options);
  }

  setIcon(value: string) {
    this.icon = value;
  }

  getIcon(): string {
    return this.get('icon');
  }
}

这里的 constructor 初始化了默认属性和控制点(Anchors)。


三、添加控制点与方法

1. 创建自定义控制点

Fabric.js 提供了控制点功能,可以通过 AnchorControl 定义。示例中使用静态方法 createAnchors 创建默认控制点:

typescript 复制代码
static createAnchors(): { anchors: Record<string, AnchorControl> } {
  return { anchors: createObjectDefaultControls() };
}

2. 自定义渲染逻辑

覆盖 _render 方法,在节点绘制时自定义渲染逻辑:

typescript 复制代码
_render(ctx: CanvasRenderingContext2D) {
  super._render(ctx);
  // 在这里添加图标或其他绘制逻辑
}

四、实现序列化和反序列化

1. 序列化

Fabric.js 对象的序列化通过 toObject 方法实现:

typescript 复制代码
toObject<SerializedComNodeProps>(
  propertiesToInclude: string[] = []
): SerializedComNodeProps {
  return super.toObject([...propertiesToInclude, 'icon']);
}

2. 反序列化

通过 fromObject 实现反序列化:

typescript 复制代码
static fromObject<T extends TOptions<SerializedComNodeProps>>(object: T) {
  return super._fromObject<ComNode>(object);
}

五、注册到 ClassRegistry

Fabric.js 使用 classRegistry 注册扩展对象:

typescript 复制代码
classRegistry.setClass(ComNode);

这样,我们可以在项目中直接使用 ComNode


六、完整代码与使用示例

以下是完整代码:

typescript 复制代码
// 导入依赖
import {
  classRegistry,
  Control,
  ObjectEvents,
  Rect,
  RectProps,
  SerializedRectProps,
  TClassProperties,
  TOptions,
} from 'fabric';
import { AnchorControl, createObjectDefaultControls } from './AnchorControl';

// 定义属性
interface UniqueComNodeProps {
  icon: string;
}

export interface SerializedComNodeProps
  extends SerializedRectProps,
    UniqueComNodeProps {}

export class ComNode<...> extends Rect {
  ...
}

// 注册类
classRegistry.setClass(ComNode);

使用示例

在 Canvas 中实例化:

typescript 复制代码
const canvas = new fabric.Canvas('canvas');

const node = new ComNode({
  left: 100,
  top: 100,
  width: 50,
  height: 50,
  icon: '📦',
  fill: 'blue',
});

canvas.add(node);

七、总结

通过扩展 Rect,我们实现了一个功能丰富的自定义节点组件 ComNode,并具备以下特性:

  1. 自定义属性(如 icon)。
  2. 灵活的控制点机制。
  3. 序列化与反序列化支持。

Fabric.js 的设计使得扩展对象变得简单,同时可以与其原生功能无缝集成。希望本文能为你提供一个清晰的 Fabric.js 入门思路,帮助你创建更多强大的图形组件!

你学废了吗?

👓都看到这了,还在乎点个赞吗?

👓都点赞了,还在乎一个收藏吗?

👓都收藏了,还在乎一个评论吗?

相关推荐
Jiaberrr1 分钟前
Vue 3 中搭建菜单权限配置界面的详细指南
前端·javascript·vue.js·elementui
科科是我嗷~5 分钟前
【uniapp】textarea maxlength字数计算不准确的问题
javascript·uni-app·html
懒大王95276 分钟前
uniapp+Vue3 组件之间的传值方法
前端·javascript·uni-app
啥都想学的又啥都不会的研究生14 分钟前
Redis设计与实现-服务器中的数据库
运维·服务器·数据库·redis·笔记·缓存·性能优化
djykkkkkk26 分钟前
ubuntu 和 RV1126 交叉编译Mosqutiio-1.6.9
linux·运维·ubuntu
大小科圣1 小时前
Tomcat介绍及部署
运维·服务器
烛阴1 小时前
秒懂 JSON:JavaScript JSON 方法详解,让你轻松驾驭数据交互!
前端·javascript
拉不动的猪1 小时前
刷刷题31(vue实际项目问题)
前端·javascript·面试
zeijiershuai1 小时前
Ajax-入门、axios请求方式、async、await、Vue生命周期
前端·javascript·ajax
拉不动的猪1 小时前
刷刷题30(vue3常规面试题)
前端·javascript·面试