iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 23
2
Modern Web

Fabricjs 筆記系列 第 23

Day 23 - Fabricjs 圖形裁切進階


接續昨天 Day 22 - Fabricjs 圖形裁切基礎介紹 繼續來做一些圖片裁切的進階操作,一樣使用 clipPath 來做更多的變化,以下是今天的大綱,。

  • 文字做為裁切遮罩
  • 巢狀裁切
    • 群組內巢狀裁切
  • 畫布裁切
    • 滑鼠應用
    • 裁切動畫

文字做為裁切遮罩

可以使用 fabric.Text 做為裁切遮罩來裁切物件,讓文字的顏色更加豐富。

一樣先使用 new fabric.Text 來建立物件,在建立一個群組將這個群組的 clipPath 設定成文字物件。

const textClip = new fabric.Text('參加鐵人賽\n一天一篇文章\n有益身心健康', {
  left: -150,
  top: -100
})

const group = new fabric.Group([
  new fabric.Rect({ width: 150, height: 100, fill: 'red' }),
  new fabric.Rect({ width: 150, height: 150, fill: 'yellow', left: 150 }),
  new fabric.Rect({ width: 150, height: 100, fill: 'blue', top: 100 }),
  new fabric.Rect({ width: 150, height: 150, fill: 'green', left: 150, top: 100 })
], {
  clipPath: textClip
})

結果

巢狀裁切

巢狀遮罩也就是切了又切,可以先將圖片做裁切,再將裁切後的物件拿去裁切別人。

這邊先將兩個圓形切齊的部分裁切出來,再拿來裁切群組矩形。

const clipPath = new fabric.Circle({radius: 100, top: -150, left: -100})
// 先切一遍
const innerClip = new fabric.Circle({radius: 100, top: 10, left: -100})
clipPath.clipPath = innerClip
// 再切一次
group.clipPath = clipPath

群組內巢狀裁切

我們甚至可以將群組內的物件先做裁切後,再將群組物件被裁切,這樣也是可行的。

const nestGroup2 = makeGroupRect(600, 0)
const circleClip = new fabric.Circle({radius: 100, top: -100, left: -100})
nestGroup2.item(0).clipPath = clipPath
nestGroup2.clipPath = circleClip

畫布裁切

Fabricjs 竟然在 canvas 也讓我們可以設定 clipPath 這個屬性,所以我們也可以透過改變 canvas.clipPath 來做到裁切整張畫布的效果!

clipPath 和一般物件裁切不同的地方,畫布裁切繪畫的起點會在左上角的位置

// 畫布裁切
const canvasClip = new fabric.Circle({radius: 100})
canvas.clipPath = canvasClip


但這邊發現超出去的畫面控制項會不見,可以透過 canvas.controlsAboveOverlay = true 來顯示被覆蓋過去的控制項。

配合滑鼠

這邊配合滑鼠事件讓畫布裁切跟著我們滑鼠來移動,會有點類似找東西的效果。

canvas.on('mouse:move', ops => {
  let e = ops.e
  canvasClip.set({
    left: e.offsetX - 100,
    top: e.offsetY - 100
  })
  canvas.renderAll()
})

結果

Day 8 - Fabricjs 事件

畫布裁切動畫

畫布的裁切也能夠配合動畫效果來做,可以做出有趣的效果。

一樣先做出裁切遮罩物件,在幫裁切物件加上動畫就可以了。

// 畫布裁切
const aniClip = new fabric.Circle({radius: 100, top: -100, left: -100})
// 建立畫布裁切動畫
nextMoving(aniClip)

canvas.clipPath = aniClip

canvas.add(aniGroup)

// 此部分同 Day 9 - Fabricjs 動畫
function nextMoving (circle) {
  circle.animate('left', getRandomInt(0, canvas.width), {
    onChange: () => {
      canvas.renderAll()
    },
    easing: fabric.util.ease.easeInOutCubic,
    duration: getRandomInt(1000, 3000)
  })
  circle.animate('radius', getRandomInt(50, 100), {
    onChange: () => {
      canvas.renderAll()
    },
    easing: fabric.util.ease.easeInOutCubic,
    duration: getRandomInt(1000, 3000)
  })
  circle.animate('top', getRandomInt(0, 100), {
    onChange: () => {
      canvas.renderAll()
    },
    onComplete: () => nextMoving(circle),
    easing: fabric.util.ease.easeInOutCubic,
    duration: getRandomInt(1000, 3000)
  })
}

Day 9 - Fabricjs 動畫

本日小結

今日利用 Fabricjs 裁切功能,做出了更多有趣的效果。

只能說 2.4.0 版本後新增的 clipPath 屬性真的是相當強大又簡單好用阿!

不論是在巢狀裁切還是配合其他如事件和動畫效果上都十分容易。

參考


上一篇
Day 22 - Fabricjs 圖形裁切基礎介紹
下一篇
Day 24 - Fabricjs 實作: 自訂圖片裁切
系列文
Fabricjs 筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言