228

Using the HTML5 <canvas> element, I would like to load an image file (PNG, JPEG, etc.), draw it to the canvas completely transparently, and then fade it in. I have figured out how to load the image and draw it to the canvas, but I don't know how to change its opacity.

Here's the code I have so far:

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';
}

Will somebody please point me in the right direction like a property to set or a function to call that will change the opacity?

Timmmm
  • 88,195
  • 71
  • 364
  • 509
Joe Lencioni
  • 10,231
  • 18
  • 55
  • 66

12 Answers12

356

I am also looking for an answer to this question, (to clarify, I want to be able to draw an image with user defined opacity such as how you can draw shapes with opacity) if you draw with primitive shapes you can set fill and stroke color with alpha to define the transparency. As far as I have concluded right now, this does not seem to affect image drawing.

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

I have concluded that setting the globalCompositeOperation works with images.

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

I wonder if there is some kind third way of setting color so that we can tint images and make them transparent easily.

EDIT:

After further digging I have concluded that you can set the transparency of an image by setting the globalAlpha parameter BEFORE you draw the image:

//works with images
ctx.globalAlpha = 0.5

If you want to achieve a fading effect over time you need some kind of loop that changes the alpha value, this is fairly easy, one way to achieve it is the setTimeout function, look that up to create a loop from which you alter the alpha over time.

Bhuwan
  • 16,525
  • 5
  • 34
  • 57
djdolber
  • 3,966
  • 2
  • 18
  • 9
  • 10
    globalAlpha works perfectly. Is part of the standard: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing – Aleris Feb 06 '11 at 16:51
  • 46
    To be precise, it's not the `canvas` element that has the `globalAlpha` property, but the context that you get from the canvas. – Steve Blackwell Jun 16 '11 at 04:21
  • 9
    Ian's comment below about ctx.save() and ctx.restore() prevents the globalAlpha from affecting the rest of the canvas. – Arosboro Mar 06 '13 at 16:32
  • 3
    Seems to me rather than controlling the opacity of what's drawn on the canvas, it would be simpler and still serve the purpose to just control the opacity of the whole canvas itself after the image is drawn (just once). Use usual CSS/style methods to do this (canvaselement.style.opacity='0.3'; etc.) Later with CSS3 you can even dispense with the loop altogether and just let the browser handle the fading instead (something like- transition: NNNms opaciity ease-in-out), or even "animate" the fading. – Chuck Kollars Nov 06 '13 at 01:03
  • Changing global alpha screws up custom fonts btw. (Whyyyyyy) – Oliver Dixon Dec 30 '14 at 05:43
  • 1
    Unfortunately, `canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";` does not work. The value must be in hex. – WebWanderer Feb 02 '15 at 18:27
  • Did you or the docs do all of these conclusions that you concluded with? :D –  Nov 03 '16 at 16:50
  • thanks for global alpha edit, It was helpfully for me – Kenny Amaro Jan 06 '17 at 14:34
  • wow that's an unfortunately value, with the rest of the channels being expressed as integers... thanks – cancerbero Aug 29 '19 at 14:35
128

Some simpler example code for using globalAlpha:

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

If you need img to be loaded:

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

Notes:

  • Set the 'src' last, to guarantee that your onload handler is called on all platforms, even if the image is already in the cache.

  • Wrap changes to stuff like globalAlpha between a save and restore (in fact use them lots), to make sure you don't clobber settings from elsewhere, particularly when bits of drawing code are going to be called from events.

Ian
  • 3,619
  • 1
  • 21
  • 32
  • globalAlpha will blur all images or drawings on a canvas, that is not what you want. – Grumpy Nov 28 '14 at 02:30
  • 7
    @Grumpy - no, `globalAlpha` doesn't blur anything. It will set the alpha for all *subsequent* drawing (it doesn't change anything already drawn), which is why in the example code I wrap it in `save` and `restore`, to limit what it applies to. – Ian Nov 29 '14 at 10:11
  • not sure that ctx.restore() will restore globalAlpha you might also need to do this at the end (at least I had to in earlier versions of Chrome) ctx.globalAlpha = 1; – Sean May 18 '17 at 15:21
  • 2
    @Sean - If you're not sure, you should check. It must have been a very old Chrome, it works on all platforms now: https://jsfiddle.net/y0z9h9m7/ – Ian May 19 '17 at 20:11
16

Edit: The answer marked as "correct" is not correct.

It's easy to do. Try this code, swapping out "ie.jpg" with whatever picture you have handy:

<!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>

The key is the globalAlpha property.

Tested with IE 9, FF 5, Safari 5, and Chrome 12 on Win7.

james.garriss
  • 12,959
  • 7
  • 83
  • 96
13

This suggestion is based on pixel manipulation in canvas 2d context.

From MDN:

You can directly manipulate pixel data in canvases at the byte level

To manipulate pixels we'll use two functions here - getImageData and putImageData.

getImageData usage:

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

The putImageData syntax:

context.putImageData(myImageData, x, y); 

Where context is your canvas 2d context, and x and y are the position on the canvas.

So to get red green blue and alpha values, we'll do the following:

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

Where x is the horizontal offset, y is the vertical offset.

The code making image half-transparent:

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

You can make you own "shaders" - see full MDN article here

Lee Goddard
  • 10,680
  • 4
  • 46
  • 63
Soul_man
  • 575
  • 5
  • 15
9

You can. Transparent canvas can be quickly faded by using destination-out global composite operation. It's not 100% perfect, sometimes it leaves some traces but it could be tweaked, depending what's needed (i.e. use 'source-over' and fill it with white color with alpha at 0.13, then fade to prepare the canvas).

// 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';
Og2t
  • 91
  • 1
  • 2
8

I think this answers the question best, it actually changes the alpha value of something that has been drawn already. Maybe this wasn't part of the api when this question was asked.

Given 2d context c.

function reduceAlpha(x, y, w, h, dA) {
    let 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 );
}
Lee Goddard
  • 10,680
  • 4
  • 46
  • 63
Dillon
  • 151
  • 1
  • 4
  • How is this answer different from Soul_man's answer given with more detail 7 years before? – BReddy May 06 '20 at 21:37
  • It's the same solution, but I have to say this is so much cleaner and easier to read, so I'm glad it was added. Personally, I'd add "c" as an argument to the function too, so that you can use it with layered canvases or multiple canvasses in a document. – user1596274 Oct 21 '20 at 10:31
  • When alpha is 0-1, use this: `screenData.data[i] = alpha * 255` – dǝɥɔS ʇoıןןƎ Dec 02 '22 at 00:39
5

Set global Alpha draw the object that has opacity then set back to normal.

  //////////////////////// circle ///////////////////////
  ctx.globalAlpha = 0.75;
  ctx.beginPath();
  ctx.arc(x1, y1, r1, 0, Math.PI*2);
  ctx.fillStyle = colour;
  ctx.fill();
  ctx.closePath();
  ctx.globalAlpha = 1;
jxwd
  • 179
  • 2
  • 6
0

How i made it..on canvas i first draw rect in a selfrun function 0,0,canvas.width,canvas.height as a background of canvas and i set globalAlpha to 1 .then i draw other shapes in ather own functions and set their globalAlpha to 0.whatever number they dont affect each other even images.

Tall
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 26 '22 at 16:25
0

Like Ian said, use c.globalAlpha = 0.5 to set the opacity, type up the rest of the settings for the square, then follow up with c.save();. This will save the settings for the square then you can c.rect and c.fillStyle the square how you want it. I chose not to wrap it with c.restore afterwards and it worked well

Lochay
  • 1
  • 1
0

you can use globalAlpha. MDN Reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha

eliasbauer
  • 11
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 24 '23 at 12:50
  • There are already other answers on this question mentioning globalAlpha, please upvote or edit those instead of posting a new answer. – LW001 Aug 25 '23 at 19:48
-1

If you use jCanvas library you can use opacity property when drawing. If you need fade effect on top of that, simply redraw with different values.

cen
  • 2,873
  • 3
  • 31
  • 56
-12

You can't. It's immediate mode graphics. But you can sort of simulate it by drawing a rectangle over it in the background color with an opacity.

If the image is over something other than a constant color, then it gets quite a bit trickier. You should be able to use the pixel manipulation methods in this case. Just save the area before drawing the image, and then blend that back on top with an opacity afterwards.

MPG
  • 835
  • 4
  • 10
  • 5
    This is not the right answer see [below](http://stackoverflow.com/questions/2359537/how-to-change-the-opacity-alpha-transparency-of-an-element-in-a-canvas-element/2675425#2675425) – Ryan Badour May 05 '11 at 17:22
  • You're correct, although you can't change the opacity of one of the elements you have drawn into the canvas, you can change the opacity of the entire canvas. In some cases that might be sufficient. – MPG May 11 '11 at 15:22
  • 2
    MPG - your comment (May 11) is also wrong. You can change the opacity of the canvas, but that's not what the OP wanted, nor what is being suggested in the answers above. – Ian Nov 03 '11 at 20:07