Chrome 设置后略微改变 RGBA 颜色的 alpha 值

Chrome slightly changes alpha-value of RGBA color after setting it

请考虑以下代码段:

var el = document.getElementById('x');
el.style.backgroundColor = "rgba(124, 181, 236, 0.25)";
alert(el.style.backgroundColor);
<div id="x">Testing</div>

在 Windows 8.1 上,这会在 IE 11 和 Firefox 37 中返回 backgroundColor 的确切输入,但在 Chrome 43 中它会更改 alpha 值,并且警报显示:

rgba(124, 181, 236, 0.247059)

请注意,alpha 值意外地 returns 0.247059 而不是 0.25

我已经完成 the background-color spec as well as the rgba spec and more specifically the bit about alpha values,但无法确定这是一个错误还是 UA(在本例中 Chrome)是否允许这样做。

是否有任何相关规范解释了 Chrome 的行为是否是 "allowed"?作为奖励,谁能解释一下 为什么 Chrome 会巧妙地改变 alpha 值?


脚注:检查它是否是 "setter" (el.style.backgroundColor = ...) 的罪魁祸首我还尝试在 DOM 本身内的元素上声明样式。这将产生相同的(意外的)结果。请参阅此片段:

document.addEventListener("DOMContentLoaded", function(event) { 
  var el = document.getElementById('x');
  alert(el.style.backgroundColor);
});
<div id="x" style="background-color: rgba(124, 181, 236, 0.25);">Testing</div>

It's a known issue of Chrome, for quite a long time...

这是由于 Chrome 如何计算 计算样式 alpha 值。

例如,您输入的 alpha 值是 0.25

  1. Chrome先将其转化为8bit级别,0.25 * 255 = 63.75.
  2. 奇怪的是,这个数字被截断为整数,63
  3. 然后,Chrome使用整数返回CSS3颜色符号,
    63/255 = 0.24705882352941178,大约 0.247059.

不仅用JS设置颜色会出现,CSS也会出现。例如:

<style>
  div { color: rgba(100, 100, 100, 0.3) }
<style>
<div></div>
<script>
  document.querySelector('div').style.color // rgba(100, 100, 100, 0.298039)
</script>

认为 RGBA 是用 32 位表示的。这意味着实际上没有 8 位 alpha 的精确 0.25 这样的东西。因此 0.247059 是实际正确的外推值。那么 Chrome 错了吗?或者它实际上是正确的吗?而其他浏览器给你一个无效的数字,它不是页面上呈现的内容的真实真实表示?

然后您可以争辩说 W3C 标准并不完全正确,它应该只允许使用 8 位 Alpha 完全设计的值。但这只是一个建议,而不是法律。 .

下面是 Chromium 自定义 webkit color.cpp 代码的精简版本,看起来可以进行颜色转换。但我不是铬专家 http://www.chromium.org/developers/how-tos/getting-around-the-chrome-source-code

来源:https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/graphics/Color.cpp

#include <iostream>

using namespace std;
typedef unsigned RGBA32;

int colorFloatToRGBAByte(float f)
{
    return std::max(0, std::min(static_cast<int>(lroundf(255.0f * f)), 255));
}

RGBA32 makeRGBA32FromFloats(float r, float g, float b, float a)
{
    cout << "Alpha: " << a;
    return colorFloatToRGBAByte(a) << 24 | colorFloatToRGBAByte(r) << 16 | colorFloatToRGBAByte(g) << 8 | colorFloatToRGBAByte(b);
}

int main()
{
        RGBA32 t;
        t = makeRGBA32FromFloats (255.0f, 255.0f, 255.0f, 0.25f);
        cout << static_cast<unsigned>(t) << std::endl;
    return 0;
}