如何应用alpha图层蒙版,使一些图像使用画布透明

时间:2016-11-16 02:51:19

标签: javascript canvas

有人可以帮我解决问题吗? 我想应用alpha图层蒙版,使一些图像使用画布透明。

非常感谢。

.product-img-list{position:relative}

alpha掩码过度https://i.stack.imgur.com/zCzOf.png

1 个答案:

答案 0 :(得分:1)

链接的图像实际上不是alpha蒙版,而是遮罩图像。不同之处在于,无光泽图像表示成为alpha通道但将其显示为RGB(或灰度)组件。它实际上没有alpha通道。哑光图像在视频合成软件中很常见,但在网络上却没那么有用。

Canvas或它使用的Porter-Duff方法不直接支持遮罩图像,因此必须先将它们转换为实际的alpha通道。要做到这一点,你必须迭代每个像素,并将其中一个组件值(从红色,绿色或蓝色 - 无关紧要)移动到alpha通道。

完成后,你可以使用现在具有合适的alpha通道的canvas对象和仅使用alpha信息的复合操作(混合模式是不同的章节)。

更好的方法当然是将图像作为PNG提供适当的alpha通道。但无论如何,为了表明它也可以使用遮罩图像,虽然效率不高,但我们可以做到以下几点:

将遮片图像转换为Alpha通道

第一步:此代码部分显示了如何有效地执行将遮罩图像转换为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);      
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ► 
<canvas id="c"></canvas>

合成

然后第二部分将使用新的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);
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ► 
<canvas id="c"></canvas>