如果多次应用,带alpha的rgba fillStyle不会完全不透明

owz*_*zim 7 javascript html5-canvas

我发现了一个奇怪的问题.以下代码导致图像逐渐消失,因为它一次又一次地被半透明的矩形透支.

但至少在draw();图像的第10次迭代应该完全透支,因为那时rect应该是完全不透明的,对吧?但它实际上永远不会完全消失.

这种效果在Chrome上比在Firefox上更糟糕.但要注意:糟糕的屏幕可能隐藏这种错误的行为=)

我还在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);

}    
});
Run Code Online (Sandbox Code Playgroud)

人们可能希望实现的效果是,一个物体在整个画布上移动,并且已经绘制的位置仅稍微透支,因此后褪色效果的余辉.但这个结果真是太可怕了.

那有什么解决方案吗?

Nei*_*eil 5

由于矩形只有 10% 不透明,因此将其绘制在图像上的结果是图像的 90% 和 10% 白色的合成。每次绘制它时,都会丢失图像上一次迭代的 10%;矩形本身并没有变得更加不透明。(要获得这种效果,您需要在图像上放置另一个对象并为其不透明度设置动画。)因此,经过 10 次迭代后,您仍然拥有(0.9^10)原始图像的大约 35%。请注意,大约 30 次迭代后可能会出现舍入误差。


Sam*_*Sam 5

我知道这很旧,但我认为先前接受的答案不正确。我认为这是由于像素值从浮点数到字节数的截断而发生的。在运行Chrome版本39.0.2171.95m的Windows 7中,经过一段时间的拨弄后,图像仍然可见,但只是轻微可见,并且似乎没有任何变化。如果我截屏,我会在图像上看到以下像素值:

(246、246、246)

用rgba在其上绘制矩形时:

(255、255、255、0.1)

并使用默认的source-over合成模式应用alpha混合,然后转换为字节,您将获得:

(255 * 0.1 + 246 * 0.9)= 246.9

因此,您可以看到,假设浏览器只是将浮点值截断为一个字节,它将写出一个246的值,并且每次重复绘制操作时,您总是会得到相同的值。

有一个在这个博客帖子上的问题的大讨论在这里

解决方法是,您可以连续清除画布并使用减小的globalAlpha值重新绘制图像。例如:

    // Clear the canvas
    ctx.globalAlpha = 1.0;
    ctx.fillStyle = "rgb(255, 255, 255)";
    ctx.fillRect(0,0,canvas.width(),canvas.height());

    // Decrement the alpha and draw the image
    alpha -= 0.1;
    if (alpha < 0) alpha = 0;
    ctx.globalAlpha = alpha;
    console.log(alpha);
    ctx.drawImage(image, 0, 0, 256, 256);
    setTimeout(draw, 100);
Run Code Online (Sandbox Code Playgroud)

小提琴在这里