•如果你看一下有關默認混合模式的canvas'context2D規範(「源在」):
http://dev.w3.org/fxtf/compositing-1/#simplealphacompositing
你會看到使用的公式是(我改名爲變量清晰度):
colorOut = prevColor x prevAlpha + newColor x newAlpha x (1 - prevAlpha)
而對於所得的α:
αlphaOut = prevAlpha + newAlpha x (1 - prevAlpha)
注意到,
a)出乎意料地,公式不是線性的(歸因於:newAlpha x(1-prevAlpha)因子)。
b)一個點有兩個較小的r,g,b值和還原的α。所以當重新使用它時, 將爲最終圖像貢獻平方(0.6)== 0.36。 (...完全違反直覺......)
•那麼60%/ 40%的抽籤會發生什麼?
1)圖片A用alpha = 60%繪製。上述 的公式給出:
colorOut = color_A * 0.6 ;
alphaOut = 0.6 ;
2)圖像B被繪製具有α= 40%
colorOut = color_A * 0.6 * 0.6 + color_B x 0.4 x (0.4);
alphaOut = 0.6 + 0.4 * 0.4;
所以最終公式==>
colorOut = 0.36 * color_A + 0.16 * color_B ;
alphaOut = 0.76 ;
你看,這不是在所有您預期的60/40混合。
•如何解決?
1)你可以用getImageData/putImageData手工完成。請注意Cross-Origin問題:如果您的圖片不是來自您的域,他們的imageData將是空的。對於表演,與畫布(= GPU)相比,下注50+的減速因子。根據圖像尺寸/計算能力/瀏覽器的不同,「實時」(= 60fps)可能無法實現。但你完全可以控制。
2)但是,如果你現在看 'ligther' 複合模式,看來我們有我們的人:現在
http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators_plus
公式爲:
colorOut = prevColor x prevAlpha + newColor x newAlpha
而對於導致阿爾法:
αlphaOut = prevAlpha + newAlpha
您會發現這是一個簡單的「加號」運算符,完美滿足您的要求。
所以解決方法是:
- 保存ctx。
- 設置較輕的複合模式。
- 以60%alpha繪製第一幅圖像。
- 以40%alpha繪製第二張圖片。
- 還原ctx。
最後的話:如果你想檢查最終α是正確的(== 255),使用該種功能:
function logAlpha(ctx,x,y) {
var imDt = ctx.getImageData(x,y,1,1).data;
if (!(imDt[0] || imDt[1] || imDt[2])) console.log('null point. CORS issue ?');
console.log(' point at (' +x+ ',' +y+ ') has an alpha of ' + imDt[3]) ;
}
「較輕」爲我工作。非常感謝!非常翔實的答案。 – phosphoer 2014-10-05 19:55:01