HTML5:在通过 JavaScript 绘制后将透明度应用于 Canvas

HTML5: Apply transparency to Canvas after drawing through JavaScript

本文关键字:透明度 应用于 Canvas 绘制 JavaScript HTML5      更新时间:2023-09-26

我正在尝试将多个对象绘制到画布元素上,然后将它们干净利落地淡出。但是,当尝试使用 globalAlpha 来实现此目的时,您可以看到通常会被遮挡的对象片段,因为每个对象都变得单独透明。解释一下:

请考虑以下代码:

context.fillStyle="yellow";
context.fillRect(0,0,100,100);
context.fillStyle="blue";
context.fillRect(50,50,100,100);

这将创建一个如下所示的图像:

Y = Yellow, B = Blue
Y Y Y Y
Y Y Y Y
Y Y B B B B
Y Y B B B B
    B B B B
    B B B B

根据需要,蓝色框完全覆盖黄色框。但是,当我们开始在组合中添加透明度时:

context.globalAlpha=0.5;
context.fillStyle="yellow";
context.fillRect(0,0,100,100);
context.fillStyle="blue";
context.fillRect(50,50,100,100);

我们最终得到这个:

Y = Yellow, B = Blue, M = Mix of both
Y Y Y Y
Y Y Y Y
Y Y M M B B
Y Y M M B B
    B B B B
    B B B B

由于蓝色矩形在绘制时是透明的,因此以前遮挡的黄色框的角现在可见。这太丑了。

请记住:淡出的画布和它背后的元素都是复杂的动态混乱;手动跟踪正在绘制的每个对象以及它们如何重叠会很快失控,同样,使用纯色叠加来"假装"淡出也不是可行的解决方案。

虽然我愿意使用 CSS 透明度来实现这一点,如果它真的是最好的方法,但我希望使用画布本身来实现这一点。我遇到过画布像素操作,这可能是一种选择,但我担心我可能会忽略一种更简单、更有效的处理方式。

有什么想法吗?

为了获得淡出当前画布的清晰效果,您可以在完全填充任何颜色时使用"目的地"操作:这使画布保持不变......除非您将 globalAlpha 降低到 x,否则生成的 alpha 将乘以 1-x。

(http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators_srcout )

杰斯宾 :

http://jsbin.com/cecavojepa/1/edit?js,output

核心褪色功能:

function fadeCanvas() {
  ctx.save();
  ctx.globalAlpha = 0.1;
  ctx.globalCompositeOperation='destination-out';
  ctx.fillStyle= '#FFF';
  ctx.fillRect(0,0,cv.width, cv.height);    
  ctx.restore();   
}

我认为最简单的解决方案就是使用CSS不透明度:

#mycanvas {opacity: 0.5}

一行,不乱。

我觉得回答我自己的问题有点傻,但是在试图解释为什么我想避免CSS时 - 因为纯画布解决方案也允许将多个画布组合成一个 - 我意识到解决方案正盯着我的脸:

在屏幕外渲染平面版本,然后使用所需的透明度将生成的图像绘制到屏幕画布上。

示例代码:

// Create an offscreen canvas large enough to fit our drawing
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.height = 150;
offscreenCanvas.width = 150;
// Draw to the offscreen canvas
var offscreenContext = offscreenCanvas.getContext("2d");
offscreenContext.fillStyle="green";
offscreenContext.fillRect(0,0,100,100);
offscreenContext.fillStyle="blue";
offscreenContext.fillRect(50,50,100,100);
// Draw our offscreen canvas to our visible canvas as an image
visibleContext.globalAlpha=0.3;
visibleContext.drawImage(offscreenCanvas, 0, 0);

这可以防止来自多个重叠对象的颜色"混合",从而实现更干净的淡入/淡出效果。