在绘制画布元素后,如何更改元素的不透明度(alpha,透明度)?


196

使用HTML5 <canvas>元素,我想加载图像文件(PNG,JPEG等),将其完全透明地绘制到画布上,然后使其淡入。我想出了如何加载图像并将其绘制到画布上。画布,但是绘制后我不知道如何更改其不透明度。

这是我到目前为止的代码:

var canvas = document.getElementById('myCanvas');

if (canvas.getContext)
{
    var c           = canvas.getContext('2d');
    c.globalAlpha   = 0;

    var img     = new Image();
    img.onload  = function() {
        c.drawImage(img, 0, 0);
    }
    img.src     = 'image.jpg';
}

有人可以将正确的方向指向我,例如要设置的属性或要调用的会改变不透明度的函数吗?

Answers:


307

我也在寻找这个问题的答案(为了澄清,我希望能够绘制具有用户定义的不透明度的图像,例如如何绘制具有不透明度的形状),如果您使用原始形状进行绘制,则可以设置填充和笔触用Alpha定义颜色以定义透明度。据我目前的结论,这似乎并不影响图像绘制。

//works with shapes but not with images
ctx.fillStyle = "rgba(255, 255, 255, 0.5)";

我得出的结论是,globalCompositeOperation用图像设置作品。

//works with images
ctx.globalCompositeOperation = "lighter";

我想知道是否存在某种第三种设置颜色的方式,以便我们可以使图像着色并使其易于透明。

编辑:

经过进一步的挖掘,我得出的结论是,可以globalAlpha在绘制图像之前通过设置参数来设置图像的透明度:

//works with images
ctx.globalAlpha = 0.5

如果要随着时间的推移实现淡入淡出效果,则需要某种可以更改Alpha值的循环,这很容易,一种实现该setTimeout功能的方法是函数,查找一个循环来更改Alpha值。时间。


7
globalAlpha完美运行。是标准的一部分:whatwg.org/specs/web-apps/current-work/multipage/…–
Aleris

42
确切地说,不是canvas具有globalAlpha属性的元素,而是从画布获得的上下文。
史蒂夫·布莱克威尔,

8
Ian在下面关于ctx.save()和ctx.restore()的评论阻止了globalAlpha影响画布的其余部分。
2013年

1
在我看来,与其控制画布上所绘制内容的不透明度,不如将其简化,并且仍然可以仅在绘制图像后(仅一次)控制整个画布本身的不透明度。使用常规的CSS /样式方法执行此操作(canvaselement.style.opacity ='0.3';等。)以后,使用CSS3,您甚至可以完全省去循环,而只需让浏览器来处理褪色(类似过渡:NNNms)不透明性),甚至“淡化”衰落。
Chuck Kollars

1
不幸的是,canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";这行不通。该值必须为十六进制。
WebWanderer

113

一些使用globalAlpha以下更简单的示例代码:

ctx.save();
ctx.globalAlpha = 0.4;
ctx.drawImage(img, x, y);
ctx.restore();

如果需要img加载:

var img = new Image();
img.onload = function() {
    ctx.save();
    ctx.globalAlpha = 0.4;
    ctx.drawImage(img, x, y);
    ctx.restore()
};
img.src = "http://...";

笔记:

  • 设置'src'最后一个,以确保onload在所有平台上都调用您的处理程序,即使映像已在缓存中也是如此。

  • 将更改包装globalAlpha在a save和之间restore(实际上经常使用它们),以确保您不会从其他地方破坏设置,尤其是当将要从事件中调用某些绘图代码时。


globalAlpha将模糊画布上的所有图像或绘图,这不是您想要的。
脾气暴躁的

6
@脾气暴躁-不,globalAlpha不模糊任何内容。它将为所有后续绘图设置Alpha (不会更改已绘制的任何内容),这就是为什么在示例代码中,我将其包装在save和中restore,以限制其适用范围。
伊恩

不确定ctx.restore()是否会还原globalAlpha,您可能还需要在最后进行此操作(至少我在较早版本的Chrome中必须这样做)ctx.globalAlpha = 1;
肖恩

1
@Sean-如果不确定,则应检查。它一定是一个非常古老的Chrome,现在可以在所有平台上使用:jsfiddle.net/y0z9h9m7
Ian,

14

编辑: 标记为“正确”的答案不正确。

这很容易做到。尝试以下代码,将“ ie.jpg”换成您拥有的任何图片:

<!DOCTYPE HTML>
<html>
    <head>
        <script>
            var canvas;
            var context;
            var ga = 0.0;
            var timerId = 0;

            function init()
            {
                canvas = document.getElementById("myCanvas");
                context = canvas.getContext("2d");
                timerId = setInterval("fadeIn()", 100);
            }

            function fadeIn()
            {
                context.clearRect(0,0, canvas.width,canvas.height);
                context.globalAlpha = ga;
                var ie = new Image();
                ie.onload = function()
                {
                    context.drawImage(ie, 0, 0, 100, 100);
                };
                ie.src = "ie.jpg";

                ga = ga + 0.1;
                if (ga > 1.0)
                {
                    goingUp = false;
                    clearInterval(timerId);
                }
            }
        </script>
    </head>
    <body onload="init()">
        <canvas height="200" width="300" id="myCanvas"></canvas>
    </body>
</html>

关键是globalAlpha属性。

在Win7上使用IE 9,FF 5,Safari 5和Chrome 12进行了测试。


13

到目前为止,该帖子已过时,我会接受我的建议。建议基于canvas 2d上下文中的像素操作。从MDN:

您可以在字节级别直接操作画布中的像素数据

为了操作像素,我们将在此处使用两个函数-getImageData和putImageData

getImageData函数的用法:

var myImageData = context.getImageData(left,top,width,height);

和putImageData语法:

context.putImageData(myImageData,dx,dy); // dx,dy-画布上的x和y偏移量

背景是你的画布2D背景

因此,要获得红色,绿色,蓝色和alpha值,我们将执行以下操作:

var r = imageData.data[((x*(imageData.width*4)) + (y*4))];
var g = imageData.data[((x*(imageData.width*4)) + (y*4)) + 1];
var b = imageData.data[((x*(imageData.width*4)) + (y*4)) + 2];
var a = imageData.data[((x*(imageData.width*4)) + (y*4)) + 3];

其中x是x偏移量,y是y在画布上的偏移量

所以我们有代码使图像半透明

var canvas = document.getElementById('myCanvas');
var c = canvas.getContext('2d');
var img = new Image();
img.onload  = function() {
   c.drawImage(img, 0, 0);
   var ImageData = c.getImageData(0,0,img.width,img.height);
   for(var i=0;i<img.height;i++)
      for(var j=0;j<img.width;j++)
         ImageData.data[((i*(img.width*4)) + (j*4) + 3)] = 127;//opacity = 0.5 [0-255]
   c.putImageData(ImageData,0,0);//put image data back
}
img.src = 'image.jpg';

您可以创建自己的“着色器”- 在此处查看完整的MDN文章


7

您可以。通过使用目标输出全局合成操作可以快速淡化透明画布。它不是100%完美的,有时会留下一些痕迹,但可以根据需要进行调整(即使用“ source-over”,并用0.13的alpha填充白色,然后淡出以准备画布)。

// Fill canvas using 'destination-out' and alpha at 0.05
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = "rgba(255, 255, 255, 0.05)";
ctx.beginPath();
ctx.fillRect(0, 0, width, height);
ctx.fill();
// Set the default mode.
ctx.globalCompositeOperation = 'source-over';

3

我认为这最好地回答了这个问题,它实际上改变了已经绘制的东西的alpha值。提出此问题时,可能这不是api的一部分。

给定2d上下文c

function reduceAlpha(x, y, w, h, dA) {
    var screenData = c.getImageData(x, y, w, h);
    for(let i = 3; i < screenData.data.length; i+=4){
    screenData.data[i] -= dA; //delta-Alpha
    }
    c.putImageData(screenData, x, y );
}

这个答案与7年前更详细地给出的Soul_man答案有何不同?
布雷迪

-2

如果使用jCanvas库,则可以在绘制时使用opacity属性。如果您还需要淡入淡出效果,只需使用不同的值重新绘制即可。


-11

你不能 它是即时模式图形。但是您可以通过在背景颜色上以不透明性在其上绘制一个矩形来对其进行模拟。

如果图像位于恒定颜色之外的其他地方,则将变得有些棘手。在这种情况下,您应该能够使用像素操作方法。只需在绘制图像之前保存该区域,然后再将其与不透明度混合回顶部即可。


5
这不是正确的答案,请参阅下面的内容
Ryan Badour 2011年

没错,尽管您无法更改已绘制到画布中的元素之一的不透明度,但是可以更改整个画布的不透明度。在某些情况下,这可能就足够了。
MPG

2
MPG-您的评论(5月11日)也有误。您可以更改画布的不透明度,但这不是OP想要的,也不是上面答案中所建议的。
伊恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.