裁切功能在一般圖片編輯軟體相當的常見,這邊也能夠透過 Fabricjs 來做圖片裁切的功能,甚至可以做出讓使用者自行決定裁切的位置,切出他們想要留下的範圍,或是用一些特別的圖形來做特別的裁切效果。
Fabricjs 提供的裁切功能,就在最近發布的 2.4.0
版本之後,能夠直接使用 Fabricjs 創建出來的物件和物件重疊,再決定裁切的效果要如何。
而在 2.4.0
版本之前則需要使用物件中的 clipTo
屬性,必須使用原生 canvas 的語法來做裁切的效果。
在 2.4.0
版本之後的這個改動,能夠讓我們更加簡單的去使用 fabricjs 所提供的裁切功能,且不須要太多原生知識就能夠執行了,不過還是保留了 2.4.0
版本之前的 clipTo
提供了更彈性的使用方法。
clipTo
屬性介紹 (2.4.0 版本之前)這邊先來簡單介紹一下 2.4.0
以前 clipTo
屬性的使用,其實使用方法也很簡單,只要將 clipTo
屬性設定為 callBack function ,並且使用 ctx 來做繪畫,使用 canvas 原生的繪圖方式畫出一個形狀之後,fabricjs render 時就會自動做裁切了。
const imgEl = document.createElement('img')
imgEl.crossOrigin = 'Anonymous'
imgEl.src = 'https://i.imgur.com/1k9XjUn.jpg'
imgEl.onload = () => {
const image = new fabric.Image(imgEl, {
scaleX: 0.5,
scaleY: 0.5,
angle: 15,
top: 60,
left: 300,
clipTo: function (ctx) {
ctx.arc(0, 0, 200, 0, Math.PI * 2, true)
}
})
canvas.add(image)
}
clipPath
屬性介紹 (2.4.0 版本之後)2.4.0
版本後,若要做裁切的功能,可以先新增一個物件暫存起來,再加入到想要裁切的物件中的 clipPath
屬性中。
讓我們來實作這部分。
這邊因為是要來拿做裁切的物件,所以它的 top
left
屬性視參照於被裁切的物件,且被裁切物件起始點為物件的中心。
// 以被裁切物件的中心為起始點
const clipPath = new fabric.Circle({
radius: 200,
top: -200, // 被裁切物件中心點為基準的 -200
left: -200 // 被裁切物件中心點為基準的 -200
})
clipPath
透過設定被裁切物件的 clipPath
屬性,指定為 clipPath
為上面新增的圓形,這樣一來,就能做出裁切的效果,圖片只顯示圓形半徑為 200 的部分,也就是兩個物件所重疊的部分。
imgEl.onload = () => {
const image = new fabric.Image(imgEl, {
scaleX: 0.5,
scaleY: 0.5,
top: 60,
left: 300,
clipPath // 這個 clipPath 為設定裁切的關鍵
})
canvas.add(image)
}
結果會同上
新的裁切功能,可以更自由的使用裁切,能夠透過群組物件 (group) ,作為裁切或是被裁切的物件。
接下來會來試試使用群組當做裁切遮罩,以及讓群組被裁切。
做出組合當作裁切遮罩
如果你想要把裁切遮罩完美的對齊正中間,請將
originX
originY
設定成 'center',且不需要再額外設定left
top
const groupClip = new fabric.Group([
new fabric.Rect({ width: 50, height: 50 }),
new fabric.Rect({ width: 50, height: 50, angle: 45 }),
new fabric.Rect({ width: 50, height: 50, angle: 90 }),
new fabric.Rect({ width: 50, height: 50, angle: 135 }),
new fabric.Rect({ width: 50, height: 50, angle: 180 }),
new fabric.Rect({ width: 50, height: 50, angle: 225 }),
new fabric.Rect({ width: 50, height: 50, angle: 270 }),
new fabric.Rect({ width: 50, height: 50, angle: 315 })
], {
scaleX: 3,
scaleY: 3,
originX: 'center',
originY: 'center'
})
再來一樣設定 clipPath
指定為 groupClip
物件。
const groupImage = new fabric.Image(imgEl, {
scaleX: 0.5,
scaleY: 0.5,
clipPath: groupClip
})
canvas.add(groupImage)
OK 完成
依照上面的邏輯,可以很間單的做出群組切群組的功能,只要好好地將 clipPath
設定好就行了。
const circleClip = new fabric.Group([
new fabric.Circle({ radius: 50, top: -50, left: -50 }),
new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black' }),
new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black', angle: 90 }),
new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black', angle: 180 }),
new fabric.Line([0, 0, 100, 100], { strokeWidth: 5, fill: 'black', stroke: 'black', angle: 270 })
])
const group = new fabric.Group([
new fabric.Rect({ width: 100, height: 100, fill: 'red' }),
new fabric.Rect({ width: 100, height: 100, fill: 'yellow', left: 100 }),
new fabric.Rect({ width: 100, height: 100, fill: 'blue', top: 100 }),
new fabric.Rect({ width: 100, height: 100, fill: 'green', left: 100, top: 100 })
], {
clipPath: circleClip
})
canvas.add(group)
今天介紹了幾種裁切物件的方式,個人覺得在 2.4.0
版本過後 Fabricjs 所提供的 clipPath
實在是相當簡單易用,尤其在群組裁切的部分,不需要自己再去用 canvas 原生 api 刻出複雜的圖形,透過搭配 fabric.Group
功能就可以做到很方便的裁切。