有人可以帮我解决这个问题吗?我想应用 alpha 图层蒙版以使用画布使某些图像透明。
非常感谢。
var redImageData = redCanvas.getContext("2d").getImageData(0, 0, 200, 200); //overlay
var ImageData = imageCanvas.getContext("2d").getImageData(0, 0, 200, 200);
var px = redImageData.data;
var px2 = ImageData.data;
for(var i = 0; i < px.length; i += 4) {
if(px[i + 0] == 0 && px[i + 1] == 0 && px[i+2] == 0){
px[i + 3] = 0;
} else {
px[i + 0] = px2[i + 0];
px[i + 1] = px2[i + 1];
px[i + 2] = px2[i + 2];
px[i + 3] = px2[i + 3];
}
}
ctx.imageSmoothingEnabled = true;
ctx.putImageData(redImageData, 0, 0);
Run Code Online (Sandbox Code Playgroud)
alpha 蒙版过度https://i.stack.imgur.com/zCzOf.png
小智 11
链接的图像并不是真正的 alpha 蒙版,而是一个磨砂图像。不同之处在于,哑光图像表示将是 alpha 通道的内容,但将其显示为 RGB(或灰度)分量。它实际上没有 alpha 通道。哑光图像在视频合成软件中很常见,但在网络上不太有用。
Canvas 或它使用的 Porter-Duff 方法不直接支持哑光图像,因此必须首先将它们转换为实际的 alpha 通道。为此,您必须遍历每个像素并将其中一个分量值(来自红色、绿色或蓝色 - 无关紧要)移动到 alpha 通道中。
完成后,您可以使用现在具有适当 alpha 通道的画布对象和仅使用 alpha 信息的复合操作(混合模式是另一章)。
更好的方法当然是提供带有适当 alpha 通道的 PNG 图像。但无论如何,为了展示也可以使用哑光图像,虽然效率不高,我们可以执行以下操作:
第一步:此代码部分展示了如何有效地执行将遮罩图像转换为 Alpha 通道的预步骤。生成的颜色对于主要合成步骤并不重要,因为它只会使用 alpha 通道,如前所述。
在尝试使用图像之前,只需确保图像已正确加载,方法是使用图像的onload回调或在所有内容加载后运行脚本。
此代码将使用像素的完整 32 位值(为了效率)简单地将组件(在这种情况下为蓝色)移动到 alpha 通道中,这使图像看起来为青色,但具有适当的 alpha,如您在橙色背景中所见显示通过(尽管大部分代码是处理加载和设置)。
window.onload = function() {
// at this stage the image has loaded:
var img = document.getElementById("img");
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
// - setup canvas to match image
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
// - draw image
ctx.drawImage(img, 0, 0);
// CONV. STEP: move a component channel to alpha-channel
var idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data32 = new Uint32Array(idata.data.buffer);
var i = 0, len = data32.length;
while(i < len) {
data32[i] = data32[i++] << 8; // shift blue channel into alpha (little-endian)
}
// update canvas
ctx.putImageData(idata, 0, 0);
};Run Code Online (Sandbox Code Playgroud)
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}Run Code Online (Sandbox Code Playgroud)
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ?
<canvas id="c"></canvas>Run Code Online (Sandbox Code Playgroud)
然后第二部分变成关于使用新的 alpha 通道进行合成。
在这种情况下,磨砂图像的黑色变得完全透明,而白色变得完全不透明。您可以在转换步骤中反转这一点,但只要您知道无光图像的外观,它就不会真正无光。
为了替换内部内容,我们使用合成模式source-in。这将根据 alpha 值替换内容,同时保持 alpha 通道的原样。
首先使用相同的模式处理内部部分允许我们在绘制框架之前对内容做额外的事情(想想小插图、阴影等)。
作为最后一步,我们使用合成模式填充透明区域,即框架本身,该模式destination-over将更透明的区域替换为绘制到画布上的内容(从概念上讲,它在现有内容的“后面”绘制)。
下面的代码使用简单的彩色框 - 只需将它们替换为您想要绘制的任何内容即可。
window.onload = function() {
var img = document.getElementById("img");
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0);
var idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data32 = new Uint32Array(idata.data.buffer);
var i = 0, len = data32.length;
while(i < len) data32[i] = data32[i++] << 8;
ctx.putImageData(idata, 0, 0);
// COMP. STEPS: use the mask with composite operation. Since our frame
// is black (= transparent as alpha) we can use the following mode:
ctx.globalCompositeOperation = "source-in";
// draw something, here a blue box, replace with whatever you want
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// to fill the frame area, still transparent, use this mode:
ctx.globalCompositeOperation = "destination-over";
ctx.fillStyle = "yellow";
ctx.fillRect(0, 0, canvas.width, canvas.height);
};Run Code Online (Sandbox Code Playgroud)
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}Run Code Online (Sandbox Code Playgroud)
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ?
<canvas id="c"></canvas>Run Code Online (Sandbox Code Playgroud)