2010-07-23 73 views
12

我一直在关注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

回答

6

我已经在这里添加了一些代码http://code.google.com/p/canvasimagegradient/,它为CanvasRenderingContext2D添加了一个drawImageGradient函数。您可以使用线性或径向渐变绘制图像。由于缺乏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); 

代码工作如下:

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

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

+0

啊,我知道后,我忘了已经指定我知道如何创建一个渐变,如https://developer.mozilla.org/samples/canvas-tutorial/4_9_canvas_lineargradient.html,我会得到这个答案。不幸的是,这些仅适用于特定颜色。如果它的图像(非纯色)另一方面这种方法根本不起作用。 – mjrevel 2010-07-24 03:43:11

+0

我回去看看图片,看看你现在想要什么。好问题。我想如果你在一个单独的画布中取出图像并检索图像数据,你可以对它应用渐变效果,然后覆盖它在原始画布上。我会玩一玩,看看我能想出什么。 – Castrohenge 2010-07-24 11:38:52

+0

听起来不错,周末不需要太多时间来处理它,但我会看到我想到的。让我张贴在任何你想出来的东西上。我绝对想要解决这个问题。 – mjrevel 2010-07-25 03:18:18

14

它可能使用上下文。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); 

这不每个像素处理做的,应该是更快

+1

我同意这应该更快,可能是正确的答案。 – calipoop 2014-03-15 18:09:54

+0

据我所见,这不是正确答案的原因是您只使用渐变来影响纯色矩形。 OP询问使用渐变来影响图像。 – Nathan 2015-02-25 16:21:07

+0

@Nathan你错了 - 这个效果很好 – Alnitak 2015-02-25 16:52:16

8

要使用透明面罩它的第一个必要采取两个图像中的一个,并把它正确合并两个图像到关闭屏幕帆布,并添加使用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); 

然后,为了真正合并两个图像,你个所需的透明面具恩需要将其他图像绘制到另一个画布,然后简单地画阿尔法复合屏幕外的画布上,最重要的是:

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); 

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

+2

这应该是被接受的答案。它的工作原理和@Castrohenge的解决方案一样好,但不需要(慢)逐像素操作。谢谢! – Nathan 2015-02-28 14:06:24