【问题标题】:HtmlCanvas + globalAlpha + overlap = incorrect output colorHtmlCanvas + globalAlpha + 重叠 = 输出颜色不正确
【发布时间】:2021-08-21 21:47:24
【问题描述】:

我想画一堆几乎透明的、相互重叠的白色矩形。

每个矩形的不透明度为 0.01

我有 100 个重叠的矩形,我希望输出结果是所有不透明度的总和。换句话说,我希望结果是没有任何不透明度的白色。

但事实并非如此。

  1. 为什么?
  2. 如何得到我想要的结果?

这里有一个极简代码来说明问题

let canvas = document.createElement("canvas");
canvas.width = canvas.height = 512;

let ctx = canvas.getContext("2d");
ctx.fillStyle = "#000000";
ctx.fillRect(0,0,512,512);

ctx.fillStyle = "#ffffff";
ctx.globalAlpha = 0.01;

for(let i=0;i<100;i++){
   let n = i*3;
   ctx.fillRect(n,n,512-n,512-n);
}

document.body.appendChild(canvas); 

这是结果

这里是 jsfiddle https://jsfiddle.net/hsqpno04/

非常欢迎任何帮助!

【问题讨论】:

    标签: javascript canvas opacity alpha overlapping


    【解决方案1】:

    要做两种RGBA颜色的alpha混合(假设正常混合和复合模式),一般公式是

    out = alpha * new + (1 - alpha) * old
    

    但是out 必须是一个整数(在 0~255 范围内),所以我们必须在此之上应用舍入(我猜舍入可能取决于实现以及它们如何存储颜色值)。

    如果我们取一个不那么戏剧性的 alpha 0.1,并保持白色,那么 new 是 255(白色是 255、255、255),而 old 是 0(透明),
    第一步,我们将拥有

    out = round( 0.1 * 255 + (1 - 0.1) * 0 );
    // => 26
    

    我们将按照以下步骤进行

    out = round( 0.1 * 255 + (1 - 0.1) * 26 );
    // => 49
    out = round( 0.1 * 255 + (1 - 0.1) * 49 );
    // => 70
    out = round( 0.1 * 255 + (1 - 0.1) * 70 );
    // => 89
    [...] // a few iterations later
    // => 250
    out = round( 0.1 * 255 + (1 - 0.1) * 250 );
    // => 251
    out = round( 0.1 * 255 + (1 - 0.1) * 251 );
    // => 251
    out = round( 0.1 * 255 + (1 - 0.1) * 251 );
    // => 251
    

    一旦达到251, 251, 251 颜色值,无论您添加多少个新图层,它都不会再改变颜色值,因此您将永远无法达到完全不透明的颜色如果不透明度小于 0.5,则分层该颜色的半透明版本。

    您的0.01 值将需要更多次迭代才能达到此稳定位置(153 对 38),但它会以较低的值(206)实现。

    round( 0.01 * 255 + (1 - 0.01) * 206 )
    // => 206
    

    请注意,颜色的存储通常与其 alpha 相乘,这可能会在这些数字中添加一些舍入误差。

    【讨论】:

    • 感谢您的解释。昨天我几乎找到了一个没有任何逻辑的解决方案,只是通过实验(但我更喜欢了解我在做什么,所以谢谢)我昨天找到的解决方案在这里:jsfiddle.net/L25c649m
    猜你喜欢
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多