canvas 合成與裁剪

我們總是將一個圖形畫在另一個之上,對於其他更多的情況,僅僅這樣是遠遠不夠的。比如,對合成的圖形來說,繪製順序會有限制。不過,我們可以利用 globalCompositeOperation 屬性來改變這種狀況。此外,clip屬性允許我們隱藏不想看到的部分圖形。

globalCompositeOperation

我們不僅可以在已有圖形後面再畫新圖形,還可以用來遮蓋指定區域,清除畫布中的某些部分(清除區域不僅限於矩形,像clearRect()方法做的那樣)以及更多其他操作。

globalCompositeOperation = type

這個屬性設定了在畫新圖形時採用的遮蓋策略,其值是一個標識 12 種遮蓋方式的字串。

檢視下面Compositing 示例的程式碼。

source-over

這是預設設定,並在現有畫布上下文之上繪製新圖形。

canvas 合成與裁剪

source-in

新圖形只在新圖形和目標畫布重疊的地方繪製。其他的都是透明的。

canvas 合成與裁剪

source-out

在不與現有畫布內容重疊的地方繪製新圖形。

canvas 合成與裁剪

source-atop

新圖形只在與現有畫布內容重疊的地方繪製。

canvas 合成與裁剪

destination-over

在現有的畫布內容後面繪製新的圖形。

canvas 合成與裁剪

destination-in

現有的畫布內容保持在新圖形和現有畫布內容重疊的位置。其他的都是透明的。

canvas 合成與裁剪

destination-out

現有內容保持在新圖形不重疊的地方。

canvas 合成與裁剪

destination-atop

現有的畫布只保留與新圖形重疊的部分,新的圖形是在畫布內容後面繪製的。

canvas 合成與裁剪

lighter

兩個重疊圖形的顏色是透過顏色值相加來確定的。

canvas 合成與裁剪

copy

只顯示新圖形。

canvas 合成與裁剪

xor

影象中,那些重疊和正常繪製之外的其他地方是透明的。

canvas 合成與裁剪

multiply

將頂層畫素與底層相應畫素相乘,結果是一幅更黑暗的圖片。

canvas 合成與裁剪

screen

畫素被倒轉,相乘,再倒轉,結果是一幅更明亮的圖片。

canvas 合成與裁剪

overlay

multiply 和 screen 的結合,原本暗的地方更暗,原本亮的地方更亮。

canvas 合成與裁剪

darken

保留兩個圖層中最暗的畫素。

canvas 合成與裁剪

lighten

保留兩個圖層中最亮的畫素。

canvas 合成與裁剪

color-dodge

將底層除以頂層的反置。

canvas 合成與裁剪

color-burn

將反置的底層除以頂層,然後將結果反過來。

canvas 合成與裁剪

hard-light

螢幕相乘(A combination of multiply and screen)類似於疊加,但上下圖層互換了。

canvas 合成與裁剪

soft-light

用頂層減去底層或者相反來得到一個正值。

canvas 合成與裁剪

difference

一個柔和版本的強光(hard-light)。純黑或純白不會導致純黑或純白。

canvas 合成與裁剪

exclusion

和 difference 相似,但對比度較低。

canvas 合成與裁剪

hue

保留了底層的亮度(luma)和色度(chroma),同時採用了頂層的色調(hue)。

canvas 合成與裁剪

saturation

保留底層的亮度(luma)和色調(hue),同時採用頂層的色度(chroma)。

canvas 合成與裁剪

color

保留了底層的亮度(luma),同時採用了頂層的色調 (hue) 和色度 (chroma)。

canvas 合成與裁剪

luminosity

保持底層的色調(hue)和色度(chroma),同時採用頂層的亮度(luma)。

canvas 合成與裁剪

裁切路徑

canvas 合成與裁剪

裁切路徑和普通的 canvas 圖形差不多,不同的是它的作用是遮罩,用來隱藏不需要的部分。如右圖所示。紅邊五角星就是裁切路徑,所有在路徑以外的部分都不會在 canvas 上繪製出來。

如果和上面介紹的 globalCompositeOperation 屬性作一比較,它可以實現與 source-in 和 source-atop差不多的效果。最重要的區別是裁切路徑不會在 canvas 上繪製東西,而且它永遠不受新圖形的影響。這些特性使得它在特定區域裡繪製圖形時相當好用。

在 繪製圖形 一章中,我只介紹了 stroke 和 fill 方法,這裡介紹第三個方法clip。

clip()

將當前正在構建的路徑轉換為當前的裁剪路徑。

我們使用 clip()方法來建立一個新的裁切路徑。

預設情況下,canvas 有一個與它自身一樣大的裁切路徑(也就是沒有裁切效果)。

clip的例子

這個例子,我會用一個圓形的裁切路徑來限制隨機星星的繪製區域。

function draw() { var ctx = document。getElementById(‘canvas’)。getContext(‘2d’); ctx。fillRect(0,0,150,150); ctx。translate(75,75); // Create a circular clipping path ctx。beginPath(); ctx。arc(0,0,60,0,Math。PI*2,true); ctx。clip(); // draw background var lingrad = ctx。createLinearGradient(0,-75,0,75); lingrad。addColorStop(0, ‘#232256’); lingrad。addColorStop(1, ‘#143778’); ctx。fillStyle = lingrad; ctx。fillRect(-75,-75,150,150); // draw stars for (var j=1;j<50;j++){ ctx。save(); ctx。fillStyle = ‘#fff’; ctx。translate(75-Math。floor(Math。random()*150), 75-Math。floor(Math。random()*150)); drawStar(ctx,Math。floor(Math。random()*4)+2); ctx。restore(); }}function drawStar(ctx,r){ ctx。save(); ctx。beginPath() ctx。moveTo(r,0); for (var i=0;i<9;i++){ ctx。rotate(Math。PI/5); if(i%2 == 0) { ctx。lineTo((r/0。525731)*0。200811,0); } else { ctx。lineTo(r,0); } } ctx。closePath(); ctx。fill(); ctx。restore();}

首先,我畫了一個與 canvas 一樣大小的黑色方形作為背景,然後移動原點至中心點。然後用 clip 方法建立一個弧形的裁切路徑。裁切路徑也屬於 canvas 狀態的一部分,可以被儲存起來。如果我們在建立新裁切路徑時想保留原來的裁切路徑,我們需要做的就是儲存一下 canvas 的狀態。

裁切路徑建立之後所有出現在它裡面的東西才會畫出來。在畫線性漸變時我們就會注意到這點。然後會繪製出 50 顆隨機位置分佈(經過縮放)的星星,當然也只有在裁切路徑裡面的星星才會繪製出來。

canvas 合成與裁剪