owzim owzim - 6 months ago 23
Javascript Question

rgba fillStyle with alpha does not get fully opaque if applied multiple times

I stubled upon a weird problem. Tthe following code results in making the image fade away because it's overdrawn by a semi-opaque rect over and over again.

But at least at the 10th iteration of

draw();
the image should be completely overdrawn, because the rect should be fully opaque by then, right? But it actually never disappears completely.

This effect is worse on Chrome than it is on Firefox. But beware: bad screens may hide this faulty behaviour =)

I also made a demo on jsFiddle.

$(function () {
var canvas = $("#mycanvas"),
ctx = canvas[0].getContext("2d"),
imgUrl = "http://it-runde.de/dateien/2009/august/14/25.png";


var image = new Image();
image.src = imgUrl ;
$(image).load(function() {
ctx.drawImage(image, 0, 0, canvas.width(), canvas.height());
draw();
});

function draw() {
ctx.fillStyle = "rgba(255, 255, 255, 0.1)";
ctx.fillRect(0,0,canvas.width(),canvas.height());
setTimeout(draw, 100);

}
});


The effect one may want to achieve is that, say an object is moving all over the canvas, and the already drawn positions get overdrawn only slightly so after-glow of after-fade effect. But this result is just fugly.

So is there any solution to this?

Answer

Since the rectangle is only 10% opaque, the result of drawing it over the image is a composite of 90% of the image and 10% white. Each time you draw it you lose 10% of the previous iteration of the image; the rectangle itself does not become more opaque. (To get that effect, you would need to position another object over the image and animate its opacity.) So after 10 iterations you still have (0.9^10) or about 35% of the original image. Note that rounding errors will probably set in after about 30 iterations.