为什么圆心在 Canvas 元素中仍然透明?

why is center of the circles still transparent in Canvas element?

我正在阅读来自 MDN 的 Canvas 元素,并遇到了一个通过 globalAlpha 属性设置透明度的示例。

<!DOCTYPE html>
<html>
    <style type="text/css">
    
    canvas{
        border: 1px solid black;
    }
    </style>
    <head>
        <title>Canvas Example</title>
    </head>
    <body>
        <canvas id='tutorial' width="150" height="150"></canvas>
    </body>
    <script>
        let canvas=document.getElementById("tutorial");
        let ctx=canvas.getContext('2d');
        ctx.fillStyle="#F00";
        ctx.fillRect(0,0,75,75);
        ctx.fillStyle="#0F0"
        ctx.fillRect(75,0,75,75)
        ctx.fillStyle="#00F";
        ctx.fillRect(0,75,75,75);
        ctx.fillStyle="#0FF"
        ctx.fillRect(75,75,75,75)
        ctx.fillStyle='#FFF';
        ctx.globalAlpha=0.2;
        ctx.beginPath();
        for(let i=1;i<8;i++){
            ctx.arc(75, 75, 10*i, 0, 2 * Math.PI, true)
            ctx.fill();
        }
        ctx.fill();
    </script>
</html>

在上面的示例中,我创建了 8 个同心圆,每个圆的透明度为 0.2。但我仍然可以看到 canvas 元素的中心。

canvas 中心不应该隐藏/不透明 5 个圆圈吗?

如果我将 globalAlpha 值更改为 0.4 或 0.5,我将无法再看到 Canvas 元素的中心

示例如下:

<!DOCTYPE html>
<html>
    <style type="text/css">
    
    canvas{
        border: 1px solid black;
    }
    </style>
    <head>
        <title>Canvas Example</title>
    </head>
    <body>
        <canvas id='tutorial' width="150" height="150"></canvas>
    </body>
    <script>
        let canvas=document.getElementById("tutorial");
        let ctx=canvas.getContext('2d');
        ctx.fillStyle="#F00";
        ctx.fillRect(0,0,75,75);
        ctx.fillStyle="#0F0"
        ctx.fillRect(75,0,75,75)
        ctx.fillStyle="#00F";
        ctx.fillRect(0,75,75,75);
        ctx.fillStyle="#0FF"
        ctx.fillRect(75,75,75,75)
        ctx.fillStyle='#FFF';
        ctx.globalAlpha=0.5;
        ctx.beginPath();
        for(let i=1;i<8;i++){
            ctx.arc(75, 75, 10*i, 0, 2 * Math.PI, true)
            ctx.fill();
        }
      
    </script>
</html>

谁能解释一下,

  1. 为什么 globalAlpha 值为 0.2 而不是 0.5 时我仍然可以看到中心?

  2. 为什么堆叠 2 个不透明度为 0.5 的圆圈或堆叠 5 个不透明度为 0.2 的圆圈不会使其完全不透明?

您对 opacity/transparency 的直觉是错误的。用非正式术语来说:当您绘制一个不透明度为 50% 的圆时,这意味着像素值由 50% 的圆和之前的 50% 组成。当您绘制第二个 50% 不透明圆圈时,像素值由第二个圆圈的 50% 和之前的 50% 组成,即第一个圆圈的 50% 和圆圈之前的 50%。因此,在两个圆圈之后,像素值是第二个圆圈的 50%,第一个圆圈的 25%,以及之前的 25%。

换句话说,它实际上是乘法的,而不是加法的。将两个 50% 透明的东西放在彼此之上会使整个 (0.5 * 0.5 = 0.25) 透明,即 75% 不透明。

I'm creating 8 concentric circles each with transparency 0.2

其实那个0.2不是透明度,而是不透明度(倒数)。所以 0.2 意味着 80% 的透明度。 其次,你画了 7 个圆圈,而不是 8 个。检查你的循环条件:

for(let i=1;i<8;i++){

Shouldn't the canvas center be hidden /opaque by 5 circles?

不一定。 0.8 透明度(0.2 不透明度)仍然很多。与前一个相比,每个圆圈留下 80% 的透明度。第二个留下第一个0.8的0.8透明度,即0.8 * 0.8 = 0.64,依此类推:

circle combined transparency result
1 0.8 0.8
2 0.82 0.64
3 0.83 0.512
4 0.84 0.4096
5 0.85 0.32768
6 0.86 0.262144
7 0.87 0.2097152

所以你看到在第 7 圆画完之后,仍然有 21% 的透明度。

如果您以 0.5 的透明度重复此练习,第 7 圆将仅留下 0.57 = 0.0078125 的总透明度。这实际上意味着不透明度为 0.992。以后看不到背景是正常的。