如果我有 2 个画布彼此重叠,是否可以"lighter"实现 html 画布复合操作?



我想在绿色画布上显示白色到透明的渐变。我不希望渐变淡入暗,所以我使用"较亮"的复合操作。这非常有效。第一个渐变是我想要的。它从白色逐渐变为背景,第二个渐变使用源过来,从白色变为深色。那不是我想要的。

var ac = a.getContext('2d');
// green background
ac.fillStyle = 'green';
ac.fillRect(0, 0, 100, 100);
// white-to-transparent gradient but lighter CO
var g = ac.createLinearGradient(20, 0, 80, 0);
g.addColorStop(0, 'white');
g.addColorStop(1, 'transparent');
ac.fillStyle = g;
ac.globalCompositeOperation = 'lighter';
ac.fillRect(20, 20, 60, 10);
// white-to-transparent gradient
ac.globalCompositeOperation = 'source-over';
ac.fillRect(20, 40, 60, 10);
<canvas id="a" width=100 height=100></canvas>

因为在实际代码中,我使用复杂的合成,出于性能原因,我决定将其拆分为两个画布。背景画布为绿色,渐变显示在顶部。问题是现在"打火机"不起作用。是否有可能达到与以前情况相同的结果?

var bc = b1.getContext('2d');
// green background
bc.fillStyle = 'green';
bc.fillRect(0, 0, 100, 100);
var bc = b2.getContext('2d');
// white-to-transparent gradient but lighter CO
var g = bc.createLinearGradient(20, 0, 80, 0);
g.addColorStop(0, 'white');
g.addColorStop(1, 'transparent');
bc.fillStyle = g;
bc.globalCompositeOperation = 'lighter';
bc.fillRect(20, 20, 60, 10);
// white-to-transparent gradient
bc.globalCompositeOperation = 'source-over';
bc.fillRect(20, 40, 60, 10);
// white-to-#ffffff00 gradient source-over
var g = bc.createLinearGradient(20, 0, 80, 0);
g.addColorStop(0, 'white');
g.addColorStop(1, '#ffffff00');
bc.globalCompositeOperation = 'source-over';
bc.fillRect(20, 60, 60, 10);
// white-to-#00000000 gradient source-over
var g = bc.createLinearGradient(20, 0, 80, 0);
g.addColorStop(0, 'white');
g.addColorStop(1, '#00000000');
bc.globalCompositeOperation = 'source-over';
bc.fillRect(20, 80, 60, 10);
<div>
<canvas id="b1" width=100 height=100 style="position: fixed; left: 0; top: 0;"></canvas>  
<canvas id="b2" width=100 height=100 style="position: fixed; left: 5px; top: 5px; border: 1px solid red;"></canvas>
</div>

如您所见,没有一种组合达到相同的结果。我不能使用白色到绿色渐变,因为在实际代码中背景不仅仅是绿色。在这些演示中,我使用绿色来演示它。那么这可能吗?如何达到相同的结果?

画布复合操作仅适用于源画布,并且仅在绘制时使用。如果你想在两个画布元素之间应用效果,你需要求助于普通的CSS,如mix-blend-mode(虽然不一样(


如果你想避免重新绘制整个背景,你可以有一个单独的(也许是屏幕外的(画布,并将其复制到你的最终图像中

,并带有drawImage

var bc1 = b1.getContext('2d');
// green background
bc1.fillStyle = 'green';
bc1.fillRect(0, 0, 100, 100);
var bc2 = b2.getContext('2d');
bc2.drawImage(b1, 0, 0);
// white-to-transparent gradient but lighter CO
var g = bc2.createLinearGradient(20, 0, 80, 0);
g.addColorStop(0, 'white');
g.addColorStop(1, 'transparent');
bc2.fillStyle = g;
bc2.globalCompositeOperation = 'lighter';
bc2.fillRect(20, 20, 60, 10);
// white-to-transparent gradient
bc2.globalCompositeOperation = 'source-over';
bc2.fillRect(20, 40, 60, 10);
// white-to-#ffffff00 gradient source-over
var g = bc2.createLinearGradient(20, 0, 80, 0);
g.addColorStop(0, 'white');
g.addColorStop(1, '#ffffff00');
bc2.globalCompositeOperation = 'source-over';
bc2.fillRect(20, 60, 60, 10);
// white-to-#00000000 gradient source-over
var g = bc2.createLinearGradient(20, 0, 80, 0);
g.addColorStop(0, 'white');
g.addColorStop(1, '#00000000');
bc2.globalCompositeOperation = 'source-over';
bc2.fillRect(20, 80, 60, 10);
#b1 {
display: none
}
#b2 {
position: fixed;
left: 5px;
top: 5px;
border: 1px solid red;
}
<div>
<canvas id="b1" width="100" height="100"></canvas>
<canvas id="b2" width="100" height="100"></canvas>
</div>

最新更新