是否可以使用画布制作渐变透明/图层蒙版图像?

mjr*_*vel 13 javascript html5 transparency gradient canvas

我一直在关注Mozilla网站上有关透明度和渐变的课程:https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors但我无法弄清楚这一点一出.

我知道我可以通过png图像实现这些效果; 但是,在我正在处理的程序中,渐变会根据图像的移动位置不断变化.

这是我正在寻找的效果的一个例子. http://home.insightbb.com/~epyonxl1/gradientex.jpg

Tom*_*yka 16

可以使用context.globalCompositeOperation来创建掩码

context.drawImage(img, 0, 0, img.width, img.height, 0,0, img.width, img.height);
context.globalCompositeOperation = "destination-out";
gradient = context.createLinearGradient(0, 0, 0, img.height);
gradient.addColorStop(0, "rgba(255, 255, 255, 0.5)");
gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
context.fillStyle = gradient;
context.fillRect(0, 0, img.width, img.height);
Run Code Online (Sandbox Code Playgroud)

这不是每像素操作,应该更快

  • 我同意这应该更快,而且可能是正确的答案。 (2认同)
  • 据我所知,这不是正确答案的原因是您仅使用渐变来影响纯色矩形。OP 询问如何使用渐变来影响图像。 (2认同)

Aln*_*tak 11

要使用透明蒙版正确合并两个图像,首先需要拍摄两个图像中的一个并将其放入离屏画布,然后使用context.globalCompositeOperation = destination-out@ Tommyka的答案添加所需的透明蒙版

var offscreen = document.createElement('canvas'); // detached from DOM
var context = offscreen.getContext('2d');
context.drawImage(image1, 0, 0, image1.width, image1.height);

var gradient = context.createLinearGradient(0, 0, 0, img.height);
gradient.addColorStop(0, "rgba(255, 255, 255, 0.5)");
gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
context.globalCompositeOperation = "destination-out";
context.fillStyle = gradient;
context.fillRect(0, 0, image1.width, image1.height);
Run Code Online (Sandbox Code Playgroud)

然后,要实际合并这两个图像,您需要将另一个图像绘制到另一个画布,然后简单地在其上绘制alpha合成的屏幕外画布:

var onscreen = document.getElementById('mycanvas');
var context2 = onscreen.getContext('2d');
context2.drawImage(image2, 0, 0, image2.width, image2.height);
context2.drawImage(offscreen, 0, 0, onscreen.width, onscreen.height);
Run Code Online (Sandbox Code Playgroud)

演示http://jsfiddle.net/alnitak/rfdjoh31/4/

  • 这应该是公认的答案.它的工作原理与@ Castrohenge的解决方案一样,但不需要(慢)像素逐像素操作.谢谢! (2认同)

Cas*_*nge 7

我在http://code.google.com/p/canvasimagegradient/中添加了一些代码,它将drawImageGradient函数添加到CanvasRenderingContext2D.您可以使用线性或径向渐变绘制图像.由于缺少getImageData/putImageData支持,它在IE中不起作用,即使使用excanvas也是如此.

例如,下面的代码将使用径向渐变绘制图像(上下文检索和图像加载未显示):

var radGrad = ctx.createRadialGradient(
    img.width / 2, img.height / 2, 10, 
    img.width / 2, img.height / 2, img.width/2);
radGrad.addColorStop(0, "transparent");
radGrad.addColorStop(1, "#000");

ctx.drawImageGradient(img, 112.5, 130, radGrad);
Run Code Online (Sandbox Code Playgroud)

代码的工作原理如下:

  1. 动态创建画布元素并在其上绘制图像.
  2. 检索此新画布的imageData.
  3. 检索要在其上绘制图像的画布上的位置的imageData.
  4. 迭代目标imageData并更新每个像素,将图像和目标像素值的百分比(从梯度透明度值导出)相加.
  5. 最后将更新的图像数据放回目标画布上.

显然,随着图像变大,性能成为一个问题.http://code.google.com/p/canvasimagegradient/上的图片需要大约6-10毫秒才能绘制.1024x768图像需要大约100ms-250ms才能绘制.只要你没有动画,它仍然可以使用.

  • 要在没有逐像素操作的情况下完成同样的操作,请参阅下面的@ Alnitak的答案. (2认同)
  • @Nathan 我下载了这个已有 10 年历史的(已存档)存储库,并将其转换为使用 npm 和 webpack 的 [GitHub 项目](https://github.com/rmkane/canvas-image-gradient)。只要有时间,我就会尝试纳入 Alnitak 的[回应](/sf/answers/2014589461/)。 (2认同)