iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 26
0

DAY 26. JavaScript Canvas 操作(二)

今天來到認識Canvas的第二天
我們已經知道如何在一張畫布Canvas上揮灑顏料了
接著我們來認識一些現實畫布上做不到的事情

合成效果

如果你剛知道一些些關於photoshop等adobe的繪圖軟體
那一定對圖層這個概念不陌生,合成效果讓我們可以設定圖層覆蓋規則
如果不了解圖層也沒關係,我們直接從範例開始

globalCompositeOperation

globalCompositeOperationgetContext的一個屬性,我們在繪圖的過程中
不斷改變這個屬性,使我們在圖片結合、覆蓋上具有很大的設計彈性。

範例


// 此範例需建立多個Canvas, 因此建立一個工廠函式
// 函式僅用於生產畫布,與主題無直接關係
function Canvas(width, height) {
    const canvas = document.createElement('canvas')
    canvas.width = width
    canvas.height = height
    return [canvas, canvas.getContext('2d')]
}

// 畫布1. 實心矩形
const width = 200
const height = 200
const [canvas1, ctx1] = Canvas(width, height) 
ctx1.fillStyle = '#f1f1f1'
ctx1.fillRect(0, 0, width, height)

// 畫布2, 實心圓
const [canvas2, ctx2] = Canvas(100, 100)
ctx2.arc(50, 50, 30, 0, 2*Math.PI, false)
ctx2.fillStyle = 'rgba(255, 0, 0, .7)'
ctx2.fill()

// 畫布3, 空心圓
const [canvas3, ctx3] = Canvas(50, 50)
ctx3.beginPath()
ctx3.arc(25, 25, 15, 0, 2*Math.PI, false)
ctx3.strokeStyle = 'hsl(210, 100%, 50%)'
ctx3.lineWidth = '5'
ctx3.stroke()

// 畫布4, 三角形
const [canvas4, ctx4] = Canvas(100, 100)
ctx4.strokeStyle = 'green'
ctx4.beginPath()
ctx4.moveTo(15, 85)
ctx4.lineTo(50, 15)
ctx4.lineTo(85, 85)
ctx4.closePath()
ctx4.lineWidth = '5'
ctx4.stroke()

// 'source-over'
// 預設值,新圖蓋在舊圖之上
ctx4.globalCompositeOperation = 'source-over'
ctx4.drawImage(canvas3, 50, 50)

// 'destination-over'
// 舊圖蓋在新圖之上
ctx3.globalCompositeOperation = 'destination-over'
ctx3.drawImage(canvas2, 25, 15)

// 'xor'
// 新舊圖重疊部分其餘透明
ctx2.globalCompositeOperation = 'xor'
ctx2.drawImage(canvas1, 25, 15)

// 'destination-atop'
// 舊圖形只保留在新、舊圖形重疊的舊圖形區域,然後蓋在新圖形之上。
ctx1.globalCompositeOperation = 'destination-atop'
ctx1.drawImage(canvas4, 25, 15)

document.body.appendChild(canvas4)
document.body.appendChild(canvas3)
document.body.appendChild(canvas2)
document.body.appendChild(canvas1)

JSBin Demo
此範例首先用Canvas工廠產生了4個簡單的圖形,接個改變他們的融合屬性
最後將他們一一畫於另一張畫布之上,展示出幾個融合效果
大家可以直接看JSBin Demo的執行結果
融合屬性有非常多選擇,MDN文件的描述清晰易懂在此就不再多解釋,僅簡單示範如何操作。

裁剪路徑

剪裁路徑的概念很簡單,"設定一個我們想顯示內容的範圍"
我們能夠使用原本畫圖的方式,將想要的圖形給畫出來
接著使用clip方法代替closePath關閉繪圖路徑
接著畫布只會顯示圖形範圍內的內容。

範例

const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = 150
canvas.height = 150
ctx.fillRect(0, 0, 150, 150)

// 移動畫布中心
ctx.translate(75, 75)
ctx.beginPath()
ctx.arc(0, 0, 60, 0, Math.PI*2, true)
ctx.clip()

// 畫布中心歸位
ctx.translate(-75, -75)

// 繪製一個與畫布一樣大的圖,並填滿
ctx.fillStyle = 'rgba(0, 0, 255, .5)'
ctx.fillRect(0, 0, 150, 150)

document.body.appendChild(canvas)

JSBin Demo
這個範例首先建立了一個長寬150px的方形畫布
然後使用fillRect將畫布填滿(預設黑色)

接著移動畫布中心至畫布中點並使用arc方法繪製一個圓
然後使用clip方法關閉繪圖路徑

最後我們將畫布中心歸位至(0, 0),接著試著畫出一個與畫布依樣大的矩形
結果從範例中可以看見,我們現在只能看見clip方法設定範圍內的藍色
其餘的部分都被剪裁掉了。

參考資源

上一篇
DAY 25. JavaScript Canvas 操作
下一篇
DAY 27. JavaScript Canvas 影像處理
系列文
重新學習網頁設計30

尚未有邦友留言

立即登入留言