我們知道 Fabricjs 是以物件為主的設計理念,其實原本預設的物件就也有繼承的概念了,像是 IText
是繼承於 Text
類別。
今天就來練習如何去創建自己的類別吧,並繼承子類別的方法。
fabric.util.createClass
可以使用 Fabricjs 所提供的 fabric.util.createClass
方法,來建立一個新的類別,並且指定繼承的類別。
透過 fabric.util.createClass
建立新的類別。
const MyRect = new fabric.util.createClass({
initialize (height, width) {
this.height = height || 100
this.width = width || 100
console.log(height, width)
},
getArea () {
return this.height * this.width
}
})
console.log(MyRect)
const rect = new MyRect(100, 100)
console.log(rect.getArea()) // 10000
建立類別後我們想要使用 canvas.add()
加入我們剛剛創造的物件。
canvas.add(rect) // error
會發現錯誤
TypeError: t._set is not a function
這是因為 canvas.add()
時會用到原本預設 Fabricjs 建立的方法,而我們透過 fabric.util.createClass
所建立的類別並沒有這些方法,導致 add 失敗。
那我們該要如何解決這個問題呢?
fabric.util.createClass
可加入要繼承哪個類別的參數。
我們只要在一開始指定創造類別時指定要繼承哪個類別就可以了。
const MyRect = new fabric.util.createClass(fabric.Rect, {
...
})
這樣一來我們的 MyRect
就能繼承 fabric.Rect
囉,這樣使用 canvas.add()
就不是問題了。
但我們還想要讓自己的物件更有特色,該要怎麼做呢?
我們可以透過改變原有 fabricjs 類別的 _render() 方法,來改變物件被 Render 出來的樣子。
並且透過 callSuper()
這個方法來呼叫父類別原有的 _render()
方法,這樣就不用自己重新畫出原本的圖形囉。
fabric.util.createClass(fabric.Rect, {
...
// 更改原有的 _render 方法
_render (ctx) {
// 先畫出原本的圖形
this.callSuper('_render', ctx)
}
例如今天我們做出一個矩形上能夠有字體。
const MyRect = new fabric.util.createClass(fabric.Rect, {
...
_render (ctx) {
// 先印出原有的矩形
// 再增加自己想要的形狀
this.callSuper('_render', ctx)
ctx.font = '30px Arial'
ctx.fillStyle = 'black'
ctx.textAlign = 'center'
ctx.fillText('Hello', 0, 10)
}
})
這邊可取得 ctx
來讓我們能夠使用原生 canvas 原生 api,使用上的彈性非常大!
但這裡的 text
是寫死的,我們來試著修改 initialize
方法,透過在 new 時傳入物件,就像我們新增一個矩形那樣。
如下面那樣,自訂屬性,並且把長寬都固定在 100
// 想要像這樣
// 長寬不指定會有預設值 100
new MyRect({
text: 'Hello',
textColor: 'black'
})
我們傳入一個 options 物件,並且先呼叫父類別的 initialize
方法,把原本該有的像是 heigth
、width
... 方法給加上去。
再來使用給定預設值被且匯入,到類別中。
而在 _render
函數中,我們就可以使用我們剛剛所定義的自訂屬性 text
、textColor
囉!
const MyRect = new fabric.util.createClass(fabric.Rect, {
initialize (options) {
// 使用原方法匯入屬性
this.callSuper('initialize', options)
// 並且給定預設值
const def = {
width: 100,
height: 100,
text: 'NONO',
textColor: 'white'
}
Object.assign(this, def, options)
},
// 更改原有的 _render 方法
_render (ctx) {
this.callSuper('_render', ctx)
ctx.font = '30px Arial'
ctx.fillStyle = this.textColor
ctx.textAlign = 'center'
ctx.fillText(this.text, 0, 10)
}
})
在來我們就能夠使用 canvas.add()
新增我們所 new 出來的物件囉。
const rect = new MyRect({
text: 'OH',
textColor: 'red'
})
canvas.add(rect)
結果
了解如何透過繼承建立 fabricjs 的類別。
以及建立類別時的一些需要注意到的小地方:
_render
函數來變化繪製出來的圖形。initialize
函數,來自訂屬性和設定預設值。this.callSuper('fn')
預先來呼叫父類別的方法,省我們重複再做一次的麻煩。本日 codepen - https://codepen.io/nono1526/pen/bmZMLq?editors=1010