The reason why this is not completely white at the end is simple: You are adding a non totally transparent overlay on top of something. Regardless of how often you will do that, you will never reach the 100% as it is a asymptote behavior. Just image the following
I have a 100% red paper. And I will cover it with a 50% transparent white glas.
Then you will see 50% of the 100% => 50%.
If I do that again, your logic would say then I have 50% + 50% = 100% but thats not how it works.
You have the 50% red & 50% white glas and overlay it with another 50% white glas. That makes the glas appears 25% red and 75% white.
If you repeat that for several times, the amount of red color goes down but never reaches 0%.
The solution is that you paint the red rect again but with a higher amount of opacity. If you then reach ctx.fillStyle = 'rgba(255,255,255,1.00)'; it will fully cover the red.
Here is the example code:
const ctx = document.querySelector('canvas').getContext('2d');
// draw "red"
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 300, 200);
// draw "transparent white" repeatedly
let lastColor;
let percentDone=0;
render();
function render() {
if (getCurrentColor() !== lastColor)
console.log(lastColor = getCurrentColor());
percentDone += .005;
if (percentDone == 1) {percentDone = 1;}
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 300, 200);
ctx.fillStyle = 'rgba(255,255,255,'+percentDone+')';
ctx.fillRect(0, 0, 300, 200);
requestAnimationFrame(render);
}
function getCurrentColor() {
return ctx.getImageData(0, 0, 1, 1).data.join(',');
}
<canvas width="300" height="200"></canvas>
External: https://jsfiddle.net/Holger50/51h0yLm6/3/
€dit 1:
The color with transparency you want to add and the color on that position are compared and only the color difference is taken in account for calculation and is based on a integer division. If the calculated value is lower than 1, the color will not change and that is what happens at color strength 214 in your example.
I have tried several things out to find out why this stops on a weird step. Maybe the following helps understanding the problem: If you set the initial fill color to ctx.fillStyle = 'black'; and issue the following ctx.fillStyle = 'rgba(255,100,150,0.01)'; the stopping output is 207,43,129,255.
It seems that the new color with tranparency is calculated somehow based on the already existing value. If the difference is to low, the colors do not get added.
As example: If you use ctx.fillStyle = 'rgba(10,100,150,0.01), the red part will never grow cause internally 10*0.01 is less than 1 and therefore not taken in account (it is rounded to the next integer). You can also see that in the color values. Red is raised by 100. The console output raises by 1 each step. Blue is raised by 150 and the console raises by 2 UNTIL it reaches value 44. After that, it will only grow with step 1 until it completely stops at 129.
I have attached a second fiddle where you can see the effect.
const ctx = document.querySelector('canvas').getContext('2d');
// draw "red"
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, 300, 200);
// draw "transparent white" repeatedly
let lastColor;
render();
function render() {
if (getCurrentColor() !== lastColor)
console.log(lastColor = getCurrentColor());
ctx.fillStyle = 'rgba(10,100,150,0.01)';
ctx.fillRect(0, 0, 300, 200);
requestAnimationFrame(render);
}
function getCurrentColor() {
return ctx.getImageData(0, 0, 1, 1).data.join(',');
}
<canvas width="300" height="200"></canvas>