【问题标题】:CSS Typed OM -- parsing background color?CSS Typed OM——解析背景颜色?
【发布时间】:2020-06-17 10:04:06
【问题描述】:

const box = document.getElementById('rb');

console.log(box.computedStyleMap().get('background-color'))
.red {
  background-color: #FF0000;
}

.box {
  width: 100px;
  height: 100px;
}
<div id="rb" class="box red"></div>

使用新的 CSS 类型对象模型,我正在尝试获取此 div 的背景颜色。它给了我一个CSSStyleValue,它似乎只有一个toString() 方法。我希望它将颜色解析为 RGB 三元组或其他有用的东西,就像它对宽度所做的那样。

是否有用于解析颜色的 API,或者尚未指定?

(我知道我可以手动解析字符串,这不是问题)

【问题讨论】:

  • 我认为没有任何 API 可以做到这一点。 JS也没有任何指定的格式。你可能会得到”red”rgb()hex...
  • 一个问题:你还不知道背景颜色的原因是什么?就像,如果你控制项目,你的 javascript 应该已经知道背景是什么颜色。
  • @Akxe getComputedStyle 返回 rgb(255, 0, 0) 无论我在 Chrome 和 Firefox 中使用“red”、rgb() 还是 hex,但我不确定这是符合规范还是巧合 - - 但这确实是这个问题的核心 - 应该有一个 API,以便我们可以以一致的方式操纵颜色。
  • @frodo2975 取决于值的来源。如果我控制一切,那么是的,绝对,我只是将它们作为数字存储在内存中,而不会费心检查 DOM。但是,在某些情况下,我需要使用不受控制的 DOM 元素。

标签: javascript css cssom css-houdini


【解决方案1】:

你的前提很混乱……

CSS Typed OM 旨在检索 CSS 值,因为它们是通过解析 authored 值在内部存储的。

如果你想要一个标准化的格式化值,那么使用它是没有意义的,因为这个API实际上是为了规避当前API只返回那个格式化的值.

所以如果你真的想要一个标准化的格式化值,只需使用getComputedStyleper specs 将根据这些规则序列化 组件:

  • 如果 是解析值或计算值的组成部分,则使用 rgb()rgba() 函数表示法返回颜色,如下所示:

    1. 如果颜色的 alpha 分量等于 1,则返回不透明颜色的 rgb() 功能等效项的序列化。
    2. 如果颜色的 alpha 分量不等于 1,则返回非不透明颜色的 rgba() 功能等效项的序列化。

换句话说,如果它是不透明的,则始终为rgb(),如果它具有alpha,则始终为rgba()

document.querySelectorAll('.test > div').forEach( elem => {
  console.log( 'formatted as', getComputedStyle(elem)['background-color'] );
} );
.named-color { background-color: magenta; }
.currentcolor { background-color: currentColor; }
.no-alpha-hex { background-color: #FF00FF; }
.no-alpha-rgb { background-color: rgb(255,0,255); }
.no-alpha-rgb-perc { background-color: rgb(100%,0%,100%); }
.no-alpha-hsl { background-color: hsl(300deg, 100%, 50%); }
.no-alpha-rgba { background-color: rgb(255,0,255,1); }
.no-alpha-rgba-perc { background-color: rgb(100%,0%,100%,1); }
.no-alpha-hsla { background-color: hsl(300deg, 100%, 50%,1); }
.alpha-hex { background-color: #FF00FF80; }
.alpha-rgba { background-color: rgba(255,0,255,0.5); }
.alpha-rgba-perc { background-color: rgba(100%,0%,100%,0.5); }
.alpha-hsla { background-color: hsla(300deg, 100%, 50%,0.5); }

.test { color: magenta; }
.test > div {
  width: 100%;
  height: 5px;
}
<div class="test">
  <div class="named-color"></div>
  <div class="currentcolor"></div>
  <div class="no-alpha-hex"></div>
  <div class="no-alpha-rgb"></div>
  <div class="no-alpha-rgb-perc"></div>
  <div class="no-alpha-hsl"></div>
  <div class="no-alpha-rgba"></div>
  <div class="no-alpha-rgba-perc"></div>
  <div class="no-alpha-hsla"></div>
  
  <div class="alpha-hex"></div>
  <div class="alpha-rgba"></div>
  <div class="alpha-rgba-perc"></div>
  <div class="alpha-hsla"></div>
</div>

如果 CSS Typed OM 将引入 CSSColorValue,他们将不得不分别处理所有这些格式(以及 CSS-colors-4 引入的许多新格式),这意味着您实际上必须编写更多代码来处理所有可能的价值观。

【讨论】:

  • 嗯,感谢您引用规范。知道它始终是 rgb()rgba() 会很有帮助。但是,w.r.t CSSTOM,即使它返回所创建的值,它肯定会附带一堆 .to() 方法将其转换为您想要的格式,对吧?这就是CSSNumericValue 现在的工作方式。
  • @mpen 在它被指定甚至起草之前,很难说它会是什么。颜色不是一件容易的事,而使用 CSS-colors-4 将色彩空间带入游戏中,它不会变得更容易。但是,是的,你是对的,可能还有.to()
【解决方案2】:

您可以使用此答案中的此画布 hack 来始终获得十六进制代码:

https://stackoverflow.com/a/5999319/2095953

var ctx = document.createElement('canvas').getContext('2d');
ctx.strokeStyle = 'rgb(64, 128, 192)';
var hexColor = ctx.strokeStyle;

【讨论】:

  • 十六进制代码不再有用。我想rgb 是单独的整数(0-255),但我把它说得有点模糊,因为我不想在浏览器上强加任何特定的表示 - 只是这些值是数字的和可数学的。浮动 0-1 也是合乎逻辑的,或者如果浏览器出于某种奇怪的原因更喜欢处理 HSL/HSV,这也是可以接受的。我认为 alpha 值也应该在那里。
  • 我明白了。但是,如果性能不是问题,从十六进制转换为数字非常容易。
  • 按原样解析更容易:'rgb(64, 128, 192)'.slice(4,-1).split(', ').map(Number)
  • 但是,你不知道它会是什么格式。CSS 支持各种有趣的格式,例如redrgba(0, 0, 0, 0.5)#FFEEDDAA。您不想自己编写可以支持多种格式的解析内容。转换为十六进制是标准化它的一种方法。我承认这有点尴尬。
  • 是的....这正是我在寻找 API 的原因,我认为 CSSOM 将是可取之处。如果 strokeStyle 被规范定义为十六进制 - 你是对的,你应该得到分数,即使为它创建一个画布是一个可怕的黑客:D
【解决方案3】:

我相信 tl;dr 尚不支持,但已计划好:https://github.com/w3c/css-houdini-drafts/issues/159

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 1970-01-01
    • 2013-12-25
    • 2012-01-01
    • 2016-11-26
    • 2012-06-26
    • 2023-04-09
    相关资源
    最近更新 更多