Canvas中的剪切clip()方法
Canvas中的剪切
接下來我們要聊的不是圖像的合成,而是Canvas中的另一個有用的功能:剪切區(qū)域。它是Canvas之中由路徑所定義的一塊區(qū)域,瀏覽器會將所有的繪圖操作都限制在本區(qū)域內執(zhí)行。在默認情況下,剪輯區(qū)域的大小與Canvas畫布大小一致。除非你通過創(chuàng)建路徑并調用Canvas繪圖環(huán)境對象的clip()方法來顯式的設定剪輯區(qū)域,否則默認的剪輯區(qū)域不會影響Canvas之中所繪制的內容。然而,一旦設置好剪輯區(qū)域,那么你在Canvas之中繪制的所有內容都將局限在該區(qū)域內。這也意味著在剪輯區(qū)域以外進行繪制是沒有任何效果的。
簡單點講,Canvas的裁切路徑和普通的Canvas圖形差不多,不同的是它的作用是遮罩,用來隱藏沒有遮罩的部分。如下圖所示,紅邊五角星就是裁切路徑,所有在路徑以外的部分都不會在Canvas上繪制出來。
從上圖所示的效果來看,跟上一節(jié)介紹的globalCompositeOperation中source-in和source-atop差不多的效果。最重要的區(qū)別是裁切路徑不會在Canvas上繪制東西,而且它永遠不受新圖形的影響。這些特性使得它在特定區(qū)域里繪制圖形時相當好用。
clip()使用
上面也說了,Canvas中的clip()方法是裁切區(qū)可用于限制圖像描繪的區(qū)域,具體的用法:
使用Canvas的繪制函數(shù)比如,rect()、arc()之類的方法選擇好繪圖區(qū)域(注意:fillRect方法不起作用;需要結合closePath方法)
使用clip()函數(shù)將該區(qū)域(由rect()、arc()方法指定的繪圖區(qū)域)設定為裁選區(qū)
設定裁選區(qū)之后,無論在Canvas上繪制什么,只有落在裁選區(qū)內的那部分才能得以顯示,其余都會被遮蔽掉。
先來看一個示例,繪制一個四個圓而且未使用裁選區(qū):
ctx.save(); // 繪制第一個圓 ctx.beginPath(); ctx.fillStyle = 'tomato'; ctx.arc(cx, cy, radius, 0, Math.PI * 2, false); ctx.fill(); // 繪制第二個圓 ctx.beginPath(); ctx.fillStyle = '#333'; ctx.arc(cx + 100, cy, radius, 0, Math.PI * 2, false); ctx.fill(); // 繪制第三個圓 ctx.beginPath(); ctx.fillStyle = 'cornsilk'; ctx.arc(cx, cy + 100, radius, 0, Math.PI * 2, false); ctx.fill(); // 繪制第四個圓 ctx.beginPath(); ctx.strokeStyle = '#ccc'; ctx.lineWidth = 10; ctx.arc(cx, cy, radius, 0, Math.PI * 2, false); ctx.stroke(); ctx.restore();
看到的效果如下:
接下來我們分別來看看加上clip()的效果,先來看看在第三個圓后面添加:
// 繪制第三個圓 ctx.beginPath(); ctx.fillStyle = 'cornsilk'; ctx.arc(cx, cy + 100, radius, 0, Math.PI * 2, false); ctx.fill(); ctx.clip();
從效果圖上,可以看出第四個圓(灰色的,只有邊框的圓)只有部分繪制出來。接著往下,把clip()往上移,放到第二個圓的后面。
原理同樣的,第二個圓成為裁剪區(qū)域,第三個圓和第四個圓與第二個圓有交集的地方才會繪制出來,所以看到的效果如下:
繼續(xù)按類似的方法操作,把clip()放置在第一個圓的后面。
最終的效果,或許你已經(jīng)可以猜得到了:
取消裁切區(qū)
當使用裁切區(qū)clip()進行繪圖后,可能需要取消該裁選區(qū)或者重新定義裁切區(qū)。在Canvas中,可以通過save()函數(shù)和restore()函數(shù)來實現(xiàn)——在構建裁切區(qū)之前保存狀態(tài),完成裁切區(qū)內的繪圖之后進行狀態(tài)讀取。
同樣拿上面的示例來舉例,依舊在第三個圓后面做clip(),并且同時做restore():
// 繪制第三個圓 ctx.beginPath(); ctx.fillStyle = 'cornsilk'; ctx.arc(cx, cy + 100, radius, 0, Math.PI * 2, false); ctx.fill(); ctx.clip(); ctx.restore(); // 繪制第四個圓 ctx.beginPath(); ctx.strokeStyle = '#ccc'; ctx.lineWidth = 10; ctx.arc(cx, cy, radius, 0, Math.PI * 2, false); ctx.stroke();
和前面的示例效果不一樣,第四個灰色的邊框圓,他并沒有僅在第三個圓(裁切區(qū))繪制,而是整個繪制出來了。接著往下看,把clip()往上提,提到第二個圓之后,而restore()位置不變:
如果把clip()移動第一個圓之后,然后restore()繼續(xù)放置在第三個圓之后,看到的效果如下:
制作探照燈
通過前面的介紹,我們了解了:Canvas中的clip()方法用于從原始畫布中剪切任意形狀和尺寸。一旦剪切了某個區(qū)域,則所有之后的繪圖都會被限制在被剪切的區(qū)域內(不能訪問畫布上的其他區(qū)域)。也可以在使用clip()方法前通過使用save()方法對當前畫布區(qū)域進行保存,并在以后的任意時間通過restore()方法對其進行恢復。
根據(jù)這個原理,我們就可以很輕松的實現(xiàn)下個探照燈的效果。
使用arc()繪制一個圓形的區(qū)域,然后在其后調用clip(),設置剪切區(qū)域
使用drawImage()在畫布中繪制一個圖像
動態(tài)改變arc()的位置,從而看到一個類似探照燈的效果
該方法實現(xiàn)的效果沒有光圈的感覺,不知道大家有什么解決辦法嗎?我嘗試了繪制圓的時候使用徑向漸變變化圓的透明度,但是沒有效果。
具體的實現(xiàn)效果以及代碼可以看下面:
這個探照燈的效果是使用clip()方法來實現(xiàn)的,如果你感興趣的話,可以把這個效果的實現(xiàn)原理與文章《Canvas學習:globalCompositeOperation詳解》中提供的示例(圖像合成制作探照燈效果)對比,看看這兩者制作方案有何不同之處。
總結
這篇文章主要介紹了Canvas中的clip()方法的特性。clip()方法將剪切區(qū)域設置為當前剪切區(qū)域與當前路徑的交集。在第一次調用clip()方法之前,剪切區(qū)域與整個Canvas畫布大小一致。因為clip()方法會將剪切區(qū)域設置為當前剪切區(qū)域與當前路徑的交集,所以對該方法的調用一般都是嵌入save()和restore()方法之間的。否則,剪切區(qū)域將會越變越小,這通常不是我們想要的效果。合理的運用好clip()和save()以及restore()方法我們就可制作出不同的效果,比如文章中介紹的探照燈的效果。
原文:https://www.w3cplus.com/canvas/clip.html
總結
以上是生活随笔為你收集整理的Canvas中的剪切clip()方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jQuery.validator 详解二
- 下一篇: 苔菜(凉拌苔菜)