iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 14
2
Modern Web

Fabricjs 筆記系列 第 14

Day 14 - Fabricjs 製作子類別

我們知道 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 失敗。

那我們該要如何解決這個問題呢?

透過繼承原本 Fabricjs 提供的類別

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 方法,把原本該有的像是 heigthwidth ... 方法給加上去。

再來使用給定預設值被且匯入,到類別中。

而在 _render 函數中,我們就可以使用我們剛剛所定義的自訂屬性 texttextColor 囉!

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


上一篇
Day 13 - 把物件群組起來
下一篇
Day 15 - Fabricjs 物件控制項樣式調整
系列文
Fabricjs 筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言