iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 26
3
Modern Web

用 Javascript 當個影像魔術師系列 第 26

Day 26 - 做個梗圖編輯器 (下)

昨天做出來了基本的雛形,今天就來完善吧,目前比較嚴重的問題是在移動的時候,字體是可以被移出去邊界外

為了解決這個問題, fabric 提供了很多事件可以讓我們使用,我們可以針對個別物件進行監聽,也可以在最外層的 canvas 統一監聽。因為我們物件沒有需要特別處理,所以就統一在外面監聽,接著使用 getBoundingRect 方法獲得左右距離及寬高。

這邊的 getBoundingRect 方法是 fabirc 提供的唷,雖然跟原生的回傳值幾乎一樣。

接著就是做邊界判斷,當超出上下或左右的時候移到最近的邊界點。最後記得使用 renderAll

this.fabricCanvas.on('object:moving', e => {
        const obj = e.target
        obj.setCoords()
        const { top, left, width, height } = obj.getBoundingRect()
        if (top < 0) {
          obj.top = 0
        }
        if (top + height > this.height) {
          obj.top = this.height - height
        }
        if (left < 0) {
          obj.left = 0
        }
        if (left + width > this.width) {
          obj.left = this.width - width
        }
        this.fabricCanvas.renderAll()
      })

到這邊,邊界的問題就解決了,接著加入新增文字鈕,並且讓文字置中,計算出間距避免所有的文字都擠在一起,在設定 top 的時候會依據現在的字多寡來算出間距,並且在最後使用 centerH 來將水平位置移到中間。

const editText = new fabric.IText('點擊編輯', {
      top: 10 + this.editTexts.length * 50,
      fill: '#ffffff',
      stroke: '#000000',
      fontSize: 40,
      fontFamily: 'Microsoft JhengHei, PMingLiU, sans-serif'
    })
    this.editTexts.push(editText)
    this.fabricCanvas.add(editText)
    editText.centerH()

這樣一直新增也不會覆蓋到原本的文字。看一下到現在的成果吧

接著實作一個文字替換顏色的功能

<div class="picker">
    fill:
    <input
      type="color"
      :value="item.fill"
      @change="(e) => colorChange(e, index)"
    />
  </div>

 colorChange(e, index) {
        const target = this.editTexts[index]
        target.set('fill', e.target.value)
        this.render()
      }

這邊直接使用了原生的 color picker,不過這也是第一次使用,也是在查資料的時候才發現原生就有提供這個功能。這邊基本上功能就只剩下載囉,下載其實基本上跟之前使用方法一樣。

downloadImg() {
    const url = this.fabricCanvas.toDataURL({
      format: 'png'
    })
    const link = document.createElement('a')
    link.href = url
    link.download = 'yourname.png'
    link.click()
  }

但在使用上會出現 "SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported."
主要是因為我們這次的圖片來源是來自跨域下載,所以出於安全性原因被阻擋,為了避免這個現象,我們在讀取圖片的時候設定第三個參數

{
    crossOrigin: 'Anonymous'
}

到這邊就大功告成囉,可以成功下載,來看一下最後的成品吧

DEMO

這幾篇介紹了這個好用的 Canvas 處理套件,讓我們不必跟原生的 api 做溝通,可以使用各種方便的封裝方法,如果有使用互動的需求推薦使用這個套件,那就明天見囉!


上一篇
Day 25 - 做個梗圖編輯器 (上)
下一篇
Day 27 - handtrack.js
系列文
用 Javascript 當個影像魔術師30

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2019-12-08 05:43:41

邁向完賽XD

我要留言

立即登入留言