本文简介
点赞 + 关注 + 珍藏 = 学会了
fabric.js
在出厂时就提供了几个根底图形,比方矩形、圆形、三角形等。
但这些图形可能不能满足日常开发,咱们可能还须要一些自定义的图形。
我做了个 自定义半圆 的demo,聊聊如何创立自定义图形。
尽管 fabric.js
提供了非常简单的办法创立自定义子类,但如果须要创立简单的图形,还是须要有肯定 canvas
根底的。
如果你还不太熟悉原生 canvas
,举荐浏览 《Canvas 从入门到劝敌人放弃(图解版)》
本文所有案例都默认引入了 fabric.js
,所以不会在每段代码里反复引入了。
什么是 fabric.js 的子类?
fabric.js
类的概念其实和原生 js
的 class
差不多。
在 fabric.js
中,能够创立类,能够继承类。
比方在 官网例子 中,继承 矩形 创立进去的一个带文本的类。它领有矩形元素的所有属性和办法,同时还增加了 label
属性,能够在矩形中增加文本标签。
fabric.js 如何创立类?
文档:fabric.util.createClass
在 fabric.js
中创立类,能够应用 fabric.util.createClass()
办法。
这里借用官网的demo进行解说。
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
的值是一个办法,用于初始化。有点相似原生 js
中 class
的 constructor
。留神,是相似。
在 initialize
中接管实例化时传进来的参数。
let point = new Point(10, 20)console.log(point.x) // 10console.log(point.y) // 20console.log(point.toString()) // "10/20"
子类的继承
在创立类时,只需在 fabric.util.createClass
中传入1个对象即可。
如果创立子类时须要继承某个父类,则要在 fabric.util.createClass
中传入2个参数。
fabric.util.createClass(parentopt, propertiesopt)
parentopt
: 父类propertiesopt
创立子类的对象(和后面创立类的对象一样)
还是 官网例子 。
在后面的创立类时,咱们创立了一个 Point
的类,这个类只承受 x
和 y
属性;外部还有一个 toString()
办法。
如果咱们想在 Point
类的根底上再创立一个 ColoredPoint
类(也就是 ColoredPoint
继承 Point
),能够这样写。
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
属性了。
let redPoint = new ColoredPoint(15, 33, '#f55')console.log(redPoint.x) // 15console.log(redPoint.y) // 33console.log(redPoint.color) // "#f55"console.log(redPoint.toString()) // "15/33"
Point
里有 toString()
办法, redPoint.toString()
会先 ColoredPoint
找,找不到就从 Point
找。一层层往上找。
如果在 ColoredPoint
中又定义了 toString()
办法,就会笼罩 Point
里定义的。
// 省略局部代码// 父类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
。
// 父类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"
还能够二次包装
// 省略局部代码// ColoredPoint 的,省略局部代码toString() { return '从子类ColoredPoint调用: ' + this.callSuper('toString')}// 输入 redPoint 的,省略局部代码console.log(redPoint.toString()) // 从子类ColoredPoint调用: 15/33
继承 fabric.js 自带的图形
在官网案例中实现了这么一个成果。
上图的成果是一个继承了矩形的子类。
矩形是 fabric.js
默认提供的图形对象之一,继承矩形时只需把矩形当做 fabric.util.createClass
的第一个参数即可,而后再增加自定义性能。
// 省略局部代码// 创立带标签性能的矩形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
的属性和办法。
// 省略局部代码labeledRect.set({ label: 'trololo', fill: '#faf', rx: 10, ry: 10})
rx
和 ry
都是 fabric.Rect
的属性,能够设置圆角。
创立自定义子类
fabric.js
中的 矩形 Rect
、三角形 Triangl
、圆形 Circle
等图形元素都是继承 fabric.Object
的。
通过继承 fabric.Object
创立进去的元素对象,默认是有管制柄之类的货色。
接下来要创立的 “半圆” 元素也是继承 fabric.Object
,这是 fabric.js
提供的一个十分便当的对象。
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas><script> // 创立画布 let canvas = new fabric.Canvas('c') // 创立半圆对象,继承 fabric.Object let Semicircle = fabric.util.createClass(fabric.Object, { // 初始化 initialize(options) { this.callSuper('initialize', options) this.width = 100 this.height = 50 }, // 渲染 _render(ctx) ctx.strokeStyle = this.stroke || '#333' // 初始化描边色彩 ctx.lineWidth = this.strokeWidth || 1 // 初始化描边宽度 ctx.fillStyle = this.fill || '#333' // 初始化填充色 ctx.beginPath() // 开始绘制门路 ctx.arc(0, -25, 50, 0, 180 * Math.PI / 180) // 绘制半圆 ctx.closePath() // 完结绘制门路 ctx.stroke() // 描边 ctx.fill() // 填充 } }) // 创立一个半圆 let semicircle = new Semicircle({ top: 10, left: 10, stroke: '#7bcfa6', // 描边色 fill: '#ed5736', // 填充色 strokeWidth: 10 // 描边宽度 }) // 将半圆增加到画布里 canvas.add(semicircle)</script>
_render
提供了 ctx
参数,这个参数是 canvas
提供的一个 context
对象。通过该对象能够发明不同图形,这是 canvas
的基础知识,也是 fabric.js
创立子类时必须把握的常识。
如果对 canvas
还不太纯熟的话,能够看看 《Canvas 从入门到劝敌人放弃(图解版)》
如果你不喜爱将子类定义成一个变量,也能够把子类绑在 fabric
上。
fabric.Semicircle = fabric.util.createClass(...)// 创立一个半圆let semicircle = new fabric.Semicircle(...)
尽管这么做看上去和创立矩形、圆形等图形的写法差不多,但我还是不太倡议这么做。
因为有可能一不小心就跟 fabric
的某个属性重名,有可能就被你笼罩了本来的办法。
所以还是将子类保留到独立的变量中比拟稳。
代码仓库
⭐创立子类 createClass
举荐浏览
《Fabric.js 从入门到_ _ _ _》
《Fabric.js 管制元素层级》
《Fabric.js 动静设置字号大小》
《Fabric.js 激活输入框》
《Fabric.js 自定义选框款式》
《Fabric.js 元素核心缩放》
点赞 + 关注 + 珍藏 = 学会了
代码仓库