如何计算所需的色调旋转以生成特定颜色?

Ric*_*ing 61 css css-filters

我有一个白色图像,我用作div的背景,我想颜色以匹配主题主色.我知道我能做到:

filter: sepia() saturate(10000%) hue-rotate(30deg);
Run Code Online (Sandbox Code Playgroud)

并循环hue-rotate查找颜色,但是可以提前计算这个值吗?鉴于指定的十六进制值非常暗,我想我也需要包含invert(%)过滤器.

鉴于十六进制值#689d94什么数学做我需要做什么来计算期望hue-rotateinvert我的白色背景图像转换成相同颜色值?

编辑

这是一个div白色背景图像被绿色过滤的片段.这里的诀窍是,它是整个div被过滤的,而不仅仅是图像.如果我要div在文本中输入一些文字颜色也会变成绿色.

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat scroll 0 0 transparent;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: invert(25%) sepia() saturate(100000%) hue-rotate(174deg);
  filter: invert(25%) sepia() saturate(100000%) hue-rotate(174deg);
}
Run Code Online (Sandbox Code Playgroud)
<div>
  </div>
Run Code Online (Sandbox Code Playgroud)

小智 78

这种情况下的关键是定义初始颜色.从技术上讲,白色,黑色或任何灰度都不是实际颜色 - 您无法使其饱和或旋转.你必须以某种方式"着色"它,并且棕褐色过滤器是唯一进行某种形式着色的过滤器.

如果您的图像是纯100%红色会更容易.然后你可以直接添加目标度,并使用HSL为目标调整饱和度和亮度.对于白色起点,第一步是转换和定义中间色,以便我们稍后可以饱和并旋转它.

让我们首先使白色图像变暗并使用棕褐色来获得我们可以使用的"基色"颜色:

filter: brightness(50%) sepia(1);
Run Code Online (Sandbox Code Playgroud)

这将产生大约的RGB颜色值:

rgb(178, 160, 128)
Run Code Online (Sandbox Code Playgroud)

第二步是将其转换为HSL颜色空间,这使我们:

hsl(38, 24.5%, 60%);
Run Code Online (Sandbox Code Playgroud)

基色结果

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: brightness(50%) sepia(1);
  filter: brightness(50%) sepia(1);
}
Run Code Online (Sandbox Code Playgroud)
<div></div>
Run Code Online (Sandbox Code Playgroud)

将基色转换为目标色

这两个第一步是静态的,每当我们需要找到目标调整时,它的结果将被重用(sepia的实际值在SVG Filters规范中定义).

现在我们需要计算我们需要应用这种基色来获得目标颜色.首先将目标颜色(例如问题中给出的#689d94)转换为HSL:

hsl(170, 21.3%, 51.2%);
Run Code Online (Sandbox Code Playgroud)

然后我们必须计算它们之间的差异.通过简单地从目标中减去基数来计算色调.饱和度和亮度相同,但是当我们假设100%的基值时,我们需要从100%中减去结果,最后得到累积值的差值:

H:  170 - 38             ->  132°
S:  100 + (24.5 - 21.3)  ->  103.2%  (relative to base 100% =  3.2%)
L:  100 + (51.2 - 60.0)  ->   91.2%  (relative to base 100% = -8.8%)
Run Code Online (Sandbox Code Playgroud)

将这些值转换为过滤字符串,方法是将其附加到现有过滤器,然后将其设置在div上:

/*      ------ base color ------  -------  new target -------------------------------*/
filter: brightness(50%) sepia(1)  hue-rotate(132deg) saturate(103.2%) brightness(91.2%);
Run Code Online (Sandbox Code Playgroud)

假设已经声明了filter和divElement,那么为了设置它你可能会做这样的事情:

...
filter = "brightness(0.5) sepia(1) hue-rotate(132deg) saturate(103.2%) brightness(91.2%)";
divElement.style.filter = filter;
divElement.style.webkitFilter = filter;
Run Code Online (Sandbox Code Playgroud)

请注意,可能存在舍入错误,因为RGB表示为整数,而HSL是浮点,因此实际结果可能不准确,但它应该非常接近.

实例

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: 
      brightness(50%) sepia(1) hue-rotate(132deg) saturate(103.2%) brightness(91.2%);
  filter: 
      brightness(50%) sepia(1) hue-rotate(132deg) saturate(103.2%) brightness(91.2%);
}
Run Code Online (Sandbox Code Playgroud)
<div></div>
<span style="font:14px sans-serif;padding:7px;color:#fff;background:#689d94">
Target color</span>
Run Code Online (Sandbox Code Playgroud)

可行的替代选择是:

  • 使用已设置的颜色预定义SVG.
  • 直接在JavaScript中使用HSL/RGB并直接使用颜色修改SVG树而不是使用过滤器.过滤器在性能上是昂贵的,特别是如果许多链接在这里并且它们是页面的主要部分.并非所有浏览器都支持它们.

  • 值得注意的是[色调旋转对于纯红色,绿色或蓝色也不起作用](http://stackoverflow.com/a/19325417/2441511) (7认同)
  • 不幸的是,这个答案是错误的.它假设hue-rotate在HSL空间中运行.它不是.CSS hue-rotate基于SVG过滤器规范中定义的基础色调旋转 - 它没有HSL颜色空间的概念.不良结果不是浮点近似的结果,而是色调旋转对色彩进行野蛮量化的事实 - 特别是那些"极端" - 具有高度不等量的R/G/B. (4认同)
  • 这是一个不错的尝试,但完全是误导。 (2认同)

Mic*_*any 17

接受的答案是错误的.色调旋转不能保持饱和度或亮度,你必须做疯狂的数学计算才能得出正确的值.更简单的方法 - 这将导致正确的结果 - 是做一个引用SVG过滤器的CSS过滤器.SVG过滤器中的feColorMatrix原语允许您直接选择颜色 - 就像这样.拿你的颜色#424242 - 将每个颜色的十六进制值除以#FF(.257)并将它们放在第五列,即前三行的颜色矩阵中.像这样:

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat scroll 0 0 transparent;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: url(#colorize);
  filter: url(#colorize);
}
Run Code Online (Sandbox Code Playgroud)
<div>
  </div>

<svg>
<defs>
<filter id="colorize" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix" values="0 0 0 0 .257
                                 0 0 0 0 .257
                                 0 0 0 0 .257
                                 0 0 0 1 0"/>
 
/filter>
</defs>
</svg>
Run Code Online (Sandbox Code Playgroud)

  • 十六进制 #42 = 十进制 4*16+2 = 66。66/256 = .257 (2认同)

Ωme*_*ega 10

获得精确匹配的唯一方法是使用 SVG 颜色矩阵滤镜。

\n

对于 RGB 颜色#689d94,即rgb(104, 157, 148),将每个原色的值​​除以 255:

\n

\n

将这些权重放入 SVG<filter>矩阵(前 3 行中的 5\xe1\xb5\x97\xca\xb0 列)

\n
<svg xmlns="http://www.w3.org/2000/svg">\n  <defs>\n    <filter id="689d94" color-interpolation-filters="sRGB">\n      <feColorMatrix type="matrix" \n        values="0 0 0 0 0.40784 \n                0 0 0 0 0.61569 \n                0 0 0 0 0.58039 \n                0 0 0 1 0"/>\n    </filter>\n  </defs>\n</svg>\n
Run Code Online (Sandbox Code Playgroud)\n

必须<filter>id(我使用了RGB十六进制代码689d94),所以我们可以用它作为参考。

\n

display由于某些浏览器(例如 Firefox)如果SVG 元素的属性设置为则看不到/使用 SVG 过滤器none,并且在 HTML 代码中使用此 SVG 元素会不方便地占用一些空间,因此最好的方法是转换此 SVG进入纯内联 CSS 过滤器。

\n

要获取内联过滤器值,请采用上面列出的 SVG 代码,通过删除换行符和不必要的空格将其转换为单行,然后在前面添加url(\'data:image/svg+xml,和附加前面提到的id,如下所示#689d94\')

\n

\r\n
\r\n
<svg xmlns="http://www.w3.org/2000/svg">\n  <defs>\n    <filter id="689d94" color-interpolation-filters="sRGB">\n      <feColorMatrix type="matrix" \n        values="0 0 0 0 0.40784 \n                0 0 0 0 0.61569 \n                0 0 0 0 0.58039 \n                0 0 0 1 0"/>\n    </filter>\n  </defs>\n</svg>\n
Run Code Online (Sandbox Code Playgroud)\r\n
div {\n  background: url(\'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="71.063" height="60.938"><path d="M33.938 0l-16.97 19.906H1.625L0 21.781v8.781l1.25 1.407h4.781l5.875 28.969h46.969l6.188-28.97h4.687l1.313-1.343v-8.844L69.5 19.906H54.656L37.312 0h-3.375zm1.593 7.594l9.594 12.312H26.25l9.281-12.312zm-20.281 16s-.405 2.9 1.594 3.844c1.998.942 4.406.03 4.406.03-1.666 2.763-3.638 3.551-5.469 2.688-3.312-1.562-.531-6.562-.531-6.562zm41.188.031s2.749 4.969-.563 6.531c-2.487 1.162-4.848-1.541-5.438-2.656 0 0 2.377.88 4.375-.063 1.999-.942 1.625-3.812 1.625-3.812z"/></svg>\') no-repeat; // optimized from http://richard.parnaby-king.co.uk/basket.svg\n  background-size: 100%;\n  display: inline-block;\n  height: 5em;\n  width: 5em;\n}\n#colored {\n  filter: url(\'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"><defs><filter id="689d94" color-interpolation-filters="sRGB"><feColorMatrix type="matrix" values="0 0 0 0 0.40784 0 0 0 0 0.61569 0 0 0 0 0.58039 0 0 0 1 0"/></filter></defs></svg>#689d94\');\n  margin-left: 20px;\n}
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n