在默認情況之下,如果在Canvas之中將某個物體(源)繪制在另一個物體(目標)之上,那么瀏覽器就會簡單地把源特體的圖像疊放在目標物體圖像上面。
簡單點講,在Canvas中,把圖像源和目標圖像,通過Canvas中的globalCompositeOperation
操作,可以得到不同的效果,比如下圖:
正如上圖,紅蘋果和黑色的圓,通過globalCompositeOperation
的destination-out
就變成了被咬了一口的紅蘋果。也就是說,在Canvas中通過圖像的合成,我們可以實現一些與眾不同的效果,比如我們要制作一個刮刮卡抽獎的效果。 今天我們就來了解Canvas中的圖像合成怎么使用。
圖像合成globalCompositeOperation類型
在Canvas中globalCompositeOperation
屬性的值總共有26種類型,每種類型都將前生不一樣的效果,當然你可能看到效果都將不樣,甚至有一些效果在瀏覽器中並不能正常的渲染。不過不要緊,我們簡單的了解這26種類型其代表的含意以及產生的效果。
1 ctx.save(); 2 ctx.translate(w / 2, h / 2); 3 ctx.fillStyle = 'red'; 4 ctx.beginPath(); 5 ctx.arc(-40, 20, 80, 0, Math.PI * 2, true); 6 ctx.closePath(); 7 ctx.fill();
上面的代碼將在Canvas畫布上繪制一個半徑為80px
的紅色圓形,在這里把它稱為圖像源。
1 ctx.fillStyle = 'orange'; 2 ctx.beginPath(); 3 ctx.arc(40, 20, 80, 0, Math.PI * 2, true); 4 ctx.closePath(); 5 ctx.fill(); 6 ctx.restore();
這段代碼將在Canvas畫布上繪制一個半徑為80px
的橙色圓形,在這里把它稱為圖像目標。在圖像源和目標圖像之間設置globalCompositeOperation
的值,就可以完成圖像的合成操作:
1 ctx.save(); 2 ctx.translate(w / 2, h / 2); 3 ctx.fillStyle = 'red'; 4 ctx.beginPath(); 5 ctx.arc(-40, 20, 80, 0, Math.PI * 2, true); 6 ctx.closePath(); 7 ctx.fill(); 8 ctx.globalCompositeOperation = 'source-in'; 9 ctx.fillStyle = 'orange'; 10 ctx.beginPath(); 11 ctx.arc(40, 20, 80, 0, Math.PI * 2, true); 12 ctx.closePath(); 13 ctx.fill(); 14 ctx.restore();
此時得到的效果如下:
source-over
source-over
是globalCompositeOperation
屬性的默認值。源圖形覆蓋目標圖形,源圖形不透明的地方顯示源圖形,其余顯示目標圖形
source-in
source-in
:目標圖形和源圖形重疊且都不透明的部分才被繪制
source-out
source-out
:目標圖形和源圖形不重疊的部分會被繪制
source-atop
source-atop
:目標圖形和源圖形內容重疊的部分的目標圖形會被繪制
destination-over
destination-over
:目標圖形和源圖形內容后面的目標圖形會被繪制
destination-in
destination-in
:目標圖形和源圖形重疊的部分會被保留(源圖形),其余顯示為透明
其它的就不一一展示了。具體每個值對應的描述,可以點擊這里查閱。
具體效果可以看下面的實現效果:
結合globalAlpha控制圖像合成操作
在Canvas中有兩個屬性globalAlpha
和globalCompositeOperation
來控制圖像合成操作:
globalAlpha
:設置圖像的透明度。globalAlpha
屬性默認值為1
,表示完全不透明,並且可以設置從0
(完全透明)到1
(完全不透明)。這個值必須設置在圖形繪制之前globalCompositeOperation
:該屬性的值在globalAlpha
以及所有變換都生效后控制在當前Canvas位圖中繪制圖形
具體對應的效果可以看下面的實現效果:
合成圖像的應用示例
刮刮卡
在平時的業務中,我們常常能看到刮刮卡這樣的抽獎效果。如果我們使用Canvas來做,就會用到Canvas圖像的合成。
<div id="card"> <canvas id="canvasOne" width="500" height="300"></canvas> </div>
我們把獎品(如果是一個圖像)當作div#card
的背景展示。然后在Canvas中先繪制一個灰色的矩形(源圖像),再通過鼠標事件(或觸摸事件)來動態繪制新圖像(這個就類似筆刷),把globalCompositeOperation
屬性的值設置為destination-out
(新繪制的圖形和目標canvas中已經存在的圖形內容不重疊的部分的會被保留)。
當筆刷擦除大於一定的比例的時候需要自動擦除掉全部灰色,即刪除<canvas>
元素或者使用clearRect()
清除Canvas畫布。
這里的實現方式是:
使用 canvas 的 getImageData 方法,來獲取 canvas 上的像素信息,這個方法返回的對象的 data 屬性是一個一維數組,包含以 RGBA 順序的數據,數據使用 0 至 255(包含)的整數表示,詳細的可以看看 canvas 的像素操作。
用這個方法來判斷有多少已經擦除掉了,也就是通過一個變量來記錄有多少像素的RGBA的值是0,當變量的值超過某一個值時,就清除全部灰色。
效果代碼:
水滴擴散
實現思路
在一個 canvas 上先畫出黑白色的圖片,然后設置背景是一張彩色的圖片,鼠標點擊時,設置 canvas 的 globalCompositeOperation 屬性值為 destination-out,根據鼠標在 canvas 中的 坐標,用一個不規則的圖形逐漸增大,來擦除掉黑白色的圖片,就可以慢慢顯示彩色的背景了。
也就是說我們需要三張圖片
黑白的圖片
彩色的圖片
不規則形狀的圖片
實現效果:
探照燈
實現思路:
同樣我們設置canvas的背景為一張被掩蓋的圖片,每次繪制在canvas上填充黑色背景,將globalCompositeOperation設置為destination-out,下面繪制燈光即圓,為了讓燈光逼真,我們使用了徑向漸變顏色填充圓。
注意點
globalCompositeOperation起作用的不只是前一個繪制內容,是指已經存在的所有繪制過的路徑內容,所以用的時候要小心之前繪制的內容是否需要產生影響。
透明度的影響上面已經涉及到 globalAlpha,如果之前繪制路徑填充或者描邊使用到了透明度或者之前繪制的是張圖片,圖片本身有透明度的效果,那globalCompositeOperation都會受影響
總結
在這篇文章中我們主要介紹了Canvas的圖像合成,在Canvas中可以通過兩個屬性globalAlpha
和globalCompositeOperation
來控制圖像合成操作,實現圖像合成效果。
著作權歸作者所有。
商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
原文: https://www.w3cplus.com/canvas/compositing.html © w3cplus.com