Fabric.js 自定义子类,创建属于自己的图形~

news/2024/7/7 22:31:24

theme: smartblue

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第14篇文章,点击查看活动详情


本文简介

点赞 + 关注 + 收藏 = 学会了

fabric.js 在出厂时就提供了几个基础图形,比如矩形、圆形、三角形等。

但这些图形可能不能满足日常开发,我们可能还需要一些自定义的图形。

我做了个 自定义半圆 的demo,聊聊如何创建自定义图形。

01.png

虽然 fabric.js 提供了非常简单的方法创建自定义子类,但如果需要创建复杂的图形,还是需要有一定 canvas 基础的。

如果你还不太熟悉原生 canvas ,推荐阅读 《Canvas 从入门到劝朋友放弃(图解版)》

本文所有案例都默认引入了 fabric.js ,所以不会在每段代码里重复引入了。

什么是 fabric.js 的子类?

fabric.js 类的概念其实和原生 jsclass 差不多。

fabric.js 中,可以创建类,可以继承类。

比如在 官方例子 中,继承 矩形 创建出来的一个带文本的类。它拥有矩形元素的所有属性和方法,同时还添加了 label 属性,可以在矩形中添加文本标签。

02.png

fabric.js 如何创建类?

文档:fabric.util.createClass

fabric.js 中创建类,可以使用 fabric.util.createClass() 方法。

这里借用官方的demo进行讲解。

js let Point = fabric.util.createClass({ initialize: function(x, y) { this.x = x || 0 this.y = y || 0 }, toString: function() { return `${this.x}/${this.y}` } })

fabric.util.createClass 接受一个对象参数,并基于该对象的配置创建一个“类”。

需要留意的是 initialize 属性,initialize 的值是一个方法,用于初始化。有点类似原生 jsclassconstructor 。注意,是类似

initialize 中接收实例化时传进来的参数。

```js let point = new Point(10, 20)

console.log(point.x) // 10 console.log(point.y) // 20

console.log(point.toString()) // "10/20" ```

子类的继承

在创建类时,只需在 fabric.util.createClass 中传入1个对象即可。

如果创建子类时需要继承某个父类,则要在 fabric.util.createClass 中传入2个参数。

fabric.util.createClass(parentopt, propertiesopt)

  • parentopt: 父类
  • propertiesopt 创建子类的对象(和前面创建类的对象一样)

还是 官方例子 。

在前面的创建类时,我们创建了一个 Point 的类,这个类只接受 xy 属性;内部还有一个 toString() 方法。

如果我们想在 Point 类的基础上再创建一个 ColoredPoint 类(也就是 ColoredPoint 继承 Point),可以这样写。

js let ColoredPoint = fabric.util.createClass( // 参数1:父类 Point, // 参数2:子类 { initialize: function(x, y, color) { this.callSuper('initialize', x, y) // 传给父类的 this.color = color || '#000' // 新增的 color 属性 } } )

此时 ColoredPoint 就继承了 Point ,并在 Point 的基础上多了 color 属性了。

js let redPoint = new ColoredPoint(15, 33, '#f55') console.log(redPoint.x) // 15 console.log(redPoint.y) // 33 console.log(redPoint.color) // "#f55" console.log(redPoint.toString()) // "15/33"

Point 里有 toString() 方法, redPoint.toString() 会先 ColoredPoint 找,找不到就从 Point 找。一层层往上找。

如果在 ColoredPoint 中又定义了 toString() 方法,就会覆盖 Point 里定义的。

```js // 省略部分代码

// 父类 let Point = new fabric.util.createClass({ initialize(x, y) {...}, toString() { return this.x + '/' + this.y } })

// 子类 let ColoredPoint = fabric.util.createClass( // 参数1:父类 Point, // 参数2:子类 { initialize(x, y, color) {...}, toString() { return '雷猴' } } )

// 实例化 let redPoint = new ColoredPoint(15, 33, '#f55')

console.log(redPoint.toString()) // "雷猴" ```

如果在子类中想继承父类的方法可以使用 callSuper

```js // 父类 let Point = new fabric.util.createClass({...})

// 省略部分代码 let ColoredPoint = fabric.util.createClass( // 参数1:父类 Point, // 参数2:子类 { initialize(x, y, color) {...}, toString() { return this.callSuper('toString') } } )

// let redPoint = new ColoredPoint(15, 33, '#f55')

console.log(redPoint.toString()) // "15/33" ```

还可以二次包装

```js // 省略部分代码

// ColoredPoint 的,省略部分代码 toString() { return '从子类ColoredPoint调用: ' + this.callSuper('toString') }

// 输出 redPoint 的,省略部分代码 console.log(redPoint.toString()) // 从子类ColoredPoint调用: 15/33 ```

继承 fabric.js 自带的图形

在官方案例中实现了这么一个效果。

03.png

上图的效果是一个继承了矩形的子类。

矩形是 fabric.js 默认提供的图形对象之一,继承矩形时只需把矩形当做 fabric.util.createClass 的第一个参数即可,然后再添加自定义功能。

04.png

```js // 省略部分代码

// 创建带标签功能的矩形 const LabeledRect = fabric.util.createClass( // 要继承的是 fabric 的矩形 fabric.Rect, { type: 'labeledRect', // 添加一个 type 属性 // 初始化 initialize: function(options) { options || (options = {}) // 初始化参数,以免报错 this.callSuper('initialize', options) // 继承 this.set('label', options.label || '') // 设置 label ,默认值是空 this.set({ width: 100, height: 50 }) // 设置默认宽高 }, toObject: function() { return fabric.util.object.extend( this.callSuper('toObject'), { label: this.get('label') } ) }, // 添加渲染时的操作 render: function(ctx) { this.callSuper('render', ctx) ctx.font = this.labelFont || '20px Helevtica' ctx.fillStyle = this.labelFill || '#333' // 将 label 渲染出来 ctx.fillText( this.label, -this.width / 2, -this.height / 2 + 20 ) } } )

// 创建标签矩形 let labeledRect = new LabeledRect({ // width: 100, // height: 50, left: 100, top: 100, label: 'test', fill: '#faa' })

// 将标签矩形添加到画布中 canvas.add(labeledRect) ```

因为继承的是矩形,所以还可以使用 fabric.Rect 的属性和方法。

05.png

```js // 省略部分代码

labeledRect.set({ label: 'trololo', fill: '#faf', rx: 10, ry: 10 }) ```

rxry 都是 fabric.Rect 的属性,可以设置圆角。

创建自定义子类

fabric.js 中的 矩形 Rect三角形 Triangl圆形 Circle 等图形元素都是继承 fabric.Object 的。

通过继承 fabric.Object 创建出来的元素对象,默认是有控制柄之类的东西。

接下来要创建的 “半圆” 元素也是继承 fabric.Object ,这是 fabric.js 提供的一个非常便利的对象。

06.gif

```html

```

_render 提供了 ctx 参数,这个参数是 canvas 提供的一个 context 对象。通过该对象可以创造不同图形,这是 canvas 的基础知识,也是 fabric.js 创建子类时必须掌握的知识。

如果对 canvas 还不太熟练的话,可以看看 《Canvas 从入门到劝朋友放弃(图解版)》

如果你不喜欢将子类定义成一个变量,也可以把子类绑在 fabric 上。

```js fabric.Semicircle = fabric.util.createClass(...)

// 创建一个半圆 let semicircle = new fabric.Semicircle(...) ```

虽然这么做看上去和创建矩形、圆形等图形的写法差不多,但我还是不太建议这么做。

因为有可能一不小心就跟 fabric 的某个属性重名,有可能就被你覆盖了原本的方法。

所以还是将子类保存到独立的变量中比较稳。

代码仓库

⭐创建子类 createClass

推荐阅读

👍《Fabric.js 从入门到_ _ _ _ _ _》

👍《Fabric.js 控制元素层级》

👍《Fabric.js 动态设置字号大小》

👍《Fabric.js 激活输入框》

👍《Fabric.js 自定义选框样式》

👍《Fabric.js 元素中心缩放》

点赞 + 关注 + 收藏 = 学会了


http://lihuaxi.xjx100.cn/news/9654.html

相关文章

Hive常用语句

创建表 CREATE TABLE if not exists ${database}.ads_dd_s( register_date string COMMENT ‘日期’, order_number string COMMENT ‘流水号’, card_no string COMMENT ‘信用卡号’, rl_bank_acct_no string COMMENT ‘借记卡’, loan_init_prin int COMMENT ‘金额’, loan…

MySQL创建存储过程,事件定时执行

MySQL创建存储过程,事件定时执行 创建存储过程 Procedure格式 CREATE[DEFINER { user | CURRENT_USER }]PROCEDURE procedure_name([[IN |OUT |INOUT ] 参数名 数据类形...]) BEGIN[characteristic ...] routine_body END [end_label]IN 输入参数:调用…

国产RK3399开发板如何在Ubuntu保留文件系统

文章来源:飞凌嵌入式官网http://www.forlinx.com在Ubuntu系统的嵌入式设备开发过程中,保留文件系统或者说备份当前开发板镜像的需求在不断增加。 比如Ubuntu文件系统需要安装库文件的话直接使用apt-get工具就可以下载,但由于需要下载的核心板…

只因程序员写了一段爬虫,公司200人被端,是种什么体验?

​只因程序员写了一段爬虫,公司200人被端是种什么体验,很多人的第一反应可能都是不可能,作为程序员谁还没写过几段爬虫,不过这次可不是乱编的。 事情的起因是这样,某一个知名互联网公司,突然发现公司的服务…

【Python刷题篇】——Python入门 010 内置函数(三)

🤵‍♂️ 个人主页: 北极的三哈 个人主页 👨‍💻 作者简介:Python领域新星创作者。 📒 系列专栏:《牛客题库-Python篇》 🌐推荐《牛客网》——找工作神器|笔试题库|面试经验|实习经验内推&am…

【译】为什么Kotlin Synthetics被废弃了?我们用什么来替代?

原文链接 比较 data binding,view binding,Kotlin Synthetics和findViewById 到底要用哪一个? 最近随着Kotlin 1.4.20版本的发布,Android官方宣布将废弃Kotlin Extension的Gradle插件,并且在后续的Kotlin Release版本也…

2022年高教社杯全国大学生数学建模竞赛-【赛题解析篇】D题:气象报文信息卫星通信传输

解题思路及完整论文后续补充 比赛规则及比赛指导大家可移步2022年高教社杯全国大学生数学建模竞赛-【比赛规则篇】比赛规则及比赛指导 因为数模国赛期间比较敏感,相关附件数据无法上传,需要赛题及附件数据的可在订阅后截图私信博主。 赛题描述 在某些紧急救援任务中,需要…

SpringBoot 源码 | applicationContext.refresh() 方法解析

[TOC](SpringBoot 源码 | applicationContext.refresh() 方法解析) SpringBoot 在 SpringBoot 启动流程中,主要的两个阶段是初始化 SpringApplication 对象以及 SpringApplication.run 方法执行的内容,在 SpringApplication.run 中的刷新容器 refreshC…