如何正确叠加透明度值?如何正确拆分Alpha值?
Canvas 透明度叠加与Alpha值拆分问题
为什么两次0.5的Alpha叠加不等于1.0?
Canvas的globalAlpha不是简单的数值相加,它遵循像素颜色的Alpha合成规则——每次绘制都是把当前图形(源)和画布上已有的像素(目标)做混合,核心公式是:最终透明度 = 新图形透明度 + 已有像素透明度 × (1 - 新图形透明度)
你代码里的情况:
- 第一次画0.5透明度的蓝矩形,画布背景是全透明(透明度0),所以最终透明度是0.5,颜色是半透蓝。
- 第二次再画同样的矩形,此时已有像素透明度是0.5,代入公式算出来最终透明度是
0.5 + 0.5×(1-0.5) = 0.75,颜色虽然是纯蓝,但透明度只有0.75,所以看起来比一次画1.0透明度的淡。
如何正确叠加到目标透明度?
如果想达到和globalAlpha=1.0完全一样的效果,有两种实用方法:
方法1:直接一次绘制(最省事)
如果不需要分步叠加,直接设globalAlpha=1.0画一次就行:
ctx.globalAlpha = 1.0; ctx.fillRect(100, 0, 100, 100);
方法2:计算每次绘制的Alpha值
要是必须分多次画,就得根据目标透明度反向算每次的Alpha值。
假设要分n次画,最终总透明度要达到A(比如1.0),每次的Alpha值a得满足:总透明度 = 1 - (1 - a)^n
反过来,已知目标总透明度A,求每次的a:a = 1 - (1 - A)^(1/n)
举个例子:
- 要分2次画到总透明度=1.0,代入公式得
a=1 - (1-1)^(1/2)=1.0,这说明两次都得设1.0,完全没必要分两次。 - 要分2次画到总透明度=0.8,那每次的Alpha值是
1 - √(1-0.8) ≈ 0.5528,两次叠加后就能刚好达到0.8的透明度。
如何正确拆分Alpha值?
拆分的核心就是用上面的反向公式:
- 先确定你要的最终总透明度效果(比如完全不透明、80%不透明等)
- 确定要分几次绘制(n)
- 用公式
a = 1 - (1 - A)^(1/n)算出每次的globalAlpha值
比如要分3次画到总透明度=0.9,每次的Alpha值就是1 - (1-0.9)^(1/3) ≈ 0.536。
额外技巧:用离屏Canvas做叠加
如果需要更灵活的叠加,比如先把多个半透明图形叠在一起,再整体放到主画布,可以用离屏Canvas:
// 创建一个离屏Canvas const offscreen = document.createElement('canvas'); offscreen.width = 100; offscreen.height = 100; const offCtx = offscreen.getContext('2d'); // 在离屏Canvas上叠两次0.5 Alpha的矩形 offCtx.fillStyle = 'blue'; offCtx.globalAlpha = 0.5; offCtx.fillRect(0, 0, 100, 100); offCtx.fillRect(0, 0, 100, 100); // 把离屏Canvas的内容一次性画到主画布(此时可以设globalAlpha=1.0) ctx.globalAlpha = 1.0; ctx.drawImage(offscreen, 100, 0);
这种方式下,离屏Canvas里的叠加结果会被当成一个整体,不会再和主画布的背景混合,你看到的就是两次叠加后的真实效果。
内容的提问来源于stack exchange,提问作者ceving
相关产品推荐
相关产品推荐

