【问题标题】:HTML canvas transparency never reaches opaqueHTML 画布透明度永远不会达到不透明
【发布时间】:2017-07-21 22:45:55
【问题描述】:

我一直在用 HTML 和 JS 开发一个多人绘图应用程序,但我遇到了一个奇怪的问题。

要进行绘制,画笔图像(从 .png 加载)根据需要多次绘制到画布上(使用 drawImage),以在鼠标移动的位置形成一条连续的线。在我添加不透明度支持之前,这一切都很好。现在我可以看到,当我将不透明度调低时,即使我来回涂鸦很长时间,画布上的图像也永远不会达到我试图绘制的全色。这导致了一种奇怪的情况,我可以绘制一条实心的、完全不透明的黑线,然后将不透明度设置得很低,并尝试用透明的红色逐渐在黑线上着色,但黑色永远不会完全褪色为红色。

我不明白这里发生了什么。我制作了 a fiddle 来证明这个问题。在小提琴中,无论矩形在前一个矩形的顶部绘制多少次,它都不会变成纯黑色。

HTML:

<canvas id="myCanvas" width="300" height="150"></canvas>

Javascript:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
for(var i=0;i<10000;i++) {
    ctx.save();
    ctx.globalAlpha=0.01;
    ctx.fillStyle='black';
    ctx.fillRect(40, 40, 130, 80);
    ctx.restore();
}

这对我来说毫无意义。有谁知道为什么会发生这种情况,我该如何解决?

【问题讨论】:

  • 因为数学。当您在纯黑色上绘制 1% 的不透明红色时,结果是 1% 的红色。再做一次,它是 1.99% 的红色。下一个是 2.97% 的红色。然后是 3.94% 红色等等。 100 个应用程序后,您的红色率为 63.4%。在 500 个应用程序之后,您将获得 99.33% 的红色。但是你永远不会达到 100% 红色,因为这就是数学与几何级数一起工作的方式......现在考虑到你只有 256 个离散值来表示有多少红色,你会因为四舍五入而失败。具体来说,当您达到 rgb(207,0,0) 时,您将无法应用足够的红色来达到 208,并且您会卡住。
  • @NiettheDarkAbsol 什么?这没有任何意义。好的,所以我正在以 1% 的不透明度绘制 255,0,0。这意味着它应该每次只添加 2.55(或者四舍五入为 3)红色。它应该在 100 次迭代中达到 255 红色......哦,等等,我不知道它是如何将 g 和 b 降低到 0......嗯,也许我假设错误。不管怎样,我见过的所有其他软件最终都会变成纯色。就像我仅在 HTML 中将两个图像叠加在一起,它们会按照我的预期进行。为什么画布不一样??
  • @NiettheDarkAbsol 好吧,我会被诅咒的。我刚刚在 PhotoShop 中尝试了同样的事情,并且惊讶地发现“问题”可以完全复制!即使有数百次笔划,低不透明度的红色画笔也永远不会完全去除黑线。嗯。那么酷,这不是问题。我现在要做的就是弄清楚如何使临时笔触图层看起来与真实图层不一样......
  • @NiettheDarkAbsol 如果您将评论转换为答案(自动,假设您可以这样做,或者复制粘贴)我会接受它,因为您是正确的。

标签: javascript html5-canvas transparency


【解决方案1】:

当您使用不透明度为 A% 的颜色进行绘制时,结果将是已经存在的颜色与您正在绘制的(不透明)颜色之间的 A%。

在这种情况下,您在纯黑色上绘制 1% 不透明的红色。结果将是从黑色到红色的 1%。称之为“红黑色”。

再做一次,结果将是“红黑色”和红色之间的 1%,即 1.99% 的红色。接下来是~2.97% 的红色,然后是~3.94% 的红色,以此类推。请注意,您不是每次添加 1%,而是从上一个笔划离开您的位置向前推进 1%。

从数学上讲,您将无限接近全红色,但实际上永远无法达到。

但图形还有一个额外的因素:只有 256 个离散值表示您可以拥有多少红色:0 表示没有,最多 255 表示完全。开始时,您的 1% 将添加 2-3 个“单位”红色(取决于四舍五入)。这将持续一段时间,并逐渐下降到一次只添加 1 个“单位”。最后,达到 207。此时,还有 48 个“单位”变为全红色,其中 1% 是 0.48 个“单位”。这还不够,由于四舍五入,您将再次得到 207。这就是为什么您在一定次数的笔划后看不到任何效果的原因。

举一个更明显的例子,假设您使用 50% 不透明的红色进行绘制。第一次中风将使您到达那里的 1/2 路。第二个给出了另一半,所以 1/2 + 1/4 = 3/4。然后是 7/8,然后是 15/16……再一次,你永远也达不到它。虽然有趣的是,在这种情况下,255 个单位的东西可以帮助您,因为您将始终添加至少 0.5 个“单位”,这将向上取整为 +1,直到您达到全红。

【讨论】:

    猜你喜欢
    • 2010-09-25
    • 2022-01-26
    • 2011-03-13
    • 2012-05-07
    • 1970-01-01
    • 2020-07-12
    • 2014-01-05
    • 1970-01-01
    • 2011-08-27
    相关资源
    最近更新 更多