【问题标题】:How to calculate required hue-rotate to generate specific colour?如何计算所需的色调旋转以生成特定颜色?
【发布时间】:2015-05-16 05:13:45
【问题描述】:

我有一张白色图像,用作 div 的背景,我想着色以匹配主题的主色。我知道我可以做到:

filter: sepia() saturate(10000%) hue-rotate(30deg);

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

给定一个十六进制值#689d94,我需要进行什么数学运算来计算所需的hue-rotateinvert 值以将我的白色背景图像转换为相同的颜色?

编辑

这是 div 的 sn-p,其中白色背景图像被过滤为绿色。这里的诀窍是,被过滤的是整个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);
}
<div>
  </div>

【问题讨论】:

  • 是的,它是一个实际的背景图像。
  • 然后(再次AFAIK)..这是不可能的,过滤器应用于实际图像。
  • 您对这个问题施加了哪些限制?我认为这可能或多或少可以使用过滤器实现:url(#mySvgFilter)。这将需要能够在页面的某处包含 svg 元素或在某处托管 SVG 文件。那会是一个可行的解决方案吗?奇怪的是,在使用颜色矩阵时,我无法让颜色完全匹配(尽管它们应该),但这可能是我误解了与混合模式相关的内容。另外,如果我可能会问,您要解决的潜在问题是什么?
  • 最初我试图通过只使用一个 svg 图像来减少用户需要发出的 http 请求的数量(篮子在页面的其他地方被使用),我只是想改变使用 CSS 着色。最终,我确实使用了另外两张图片(一张是上面的深绿色,一张是黑色),但这仍然是我正在寻找答案的问题。至于限制 - 我正在寻找可以遵循的一系列步骤或程序,给定十六进制输入,给我一个过滤器和值列表,我需要使用这些过滤器和值来为我的白色图像着色。
  • 是否可以使用内嵌 svg 过滤器?

标签: css css-filters


【解决方案1】:

接受的答案是错误的。色相旋转不会保存饱和度或亮度,您必须进行疯狂的数学运算才能得出正确的值。更简单的方法 - 将产生正确的结果 - 是做一个引用 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);
}
<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>

【讨论】:

  • 这看起来是一个不错的解决方案。但是你能告诉我如何从#424242 和#FF 得到 .257、.257、.257 吗?我试着去Hex Calculator 并做十六进制 42 除以十六进制 FF,它只是告诉我十六进制值:0 余数:42,十进制值:0 余数:66。
  • 十六进制 #42 = 十进制 4*16+2 = 66. 66/256 = .257
  • @MichaelMullany 为什么除以 256,而不是 255?
  • 应该是 255 - 抱歉。
【解决方案2】:

如果使用的是 svg,那么 ...

您可以使用一些文本编辑器打开 svg 文件并复制并粘贴到 html 文件,然后根据需要更改路径颜色。

在下面的示例代码中...我只是更改了中心环的路径颜色。 希望这会有所帮助..

        var imgg =document.getElementById("path");
        imgg.style="fill:#424242";
   
<html>
<body>
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="imgg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 296.838 296.838" style="enable-background:new 0 0 296.838 296.838;" xml:space="preserve" width="512px" height="512px">
<g>
	<path  d="M58.733,64.566L41.763,47.596C14.832,74.526,0,110.333,0,148.419s14.832,73.893,41.763,100.823l16.971-16.971   C36.335,209.874,24,180.095,24,148.419S36.335,86.964,58.733,64.566z" fill="#91DC5A"/>
	<path d="M82.137,81.969c-17.75,17.748-27.525,41.348-27.525,66.45s9.775,48.702,27.525,66.45l16.971-16.971   c-13.218-13.216-20.496-30.788-20.496-49.479s7.278-36.264,20.496-49.48L82.137,81.969z" fill="#91DC5A"/>
	<path d="M255.075,47.596l-16.971,16.971c22.399,22.397,34.733,52.177,34.733,83.853s-12.335,61.455-34.733,83.852l16.971,16.971   c26.931-26.931,41.763-62.737,41.763-100.823S282.006,74.526,255.075,47.596z" fill="#91DC5A"/>
	<path d="M214.701,81.969L197.73,98.939c13.218,13.216,20.496,30.788,20.496,49.48s-7.278,36.264-20.496,49.479l16.971,16.971   c17.75-17.748,27.525-41.348,27.525-66.45S232.451,99.717,214.701,81.969z" fill="#91DC5A"/>
	<path id="path" d="M148.586,114.789c-8.607,0-17.212,3.284-23.78,9.851c-13.131,13.133-13.131,34.424,0,47.559   c6.568,6.566,15.174,9.851,23.78,9.851c8.606,0,17.212-3.284,23.779-9.851c13.131-13.135,13.131-34.426,0-47.559   C165.798,118.073,157.192,114.789,148.586,114.789z M155.395,155.228c-2.454,2.454-5.319,2.821-6.809,2.821   c-1.489,0-4.356-0.367-6.808-2.818c-3.755-3.756-3.755-9.867-0.003-13.619c2.455-2.455,5.321-2.822,6.811-2.822   c1.489,0,4.354,0.367,6.808,2.82C159.147,145.363,159.147,151.475,155.395,155.228z" fill="#91DC5A"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
    
    
</body>
</html>

背景图片

        var myimg='url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 296.838 296.838" style="enable-background:new 0 0 296.838 296.838;" xml:space="preserve" width="512px" height="512px"><g><path  d="M58.733,64.566L41.763,47.596C14.832,74.526,0,110.333,0,148.419s14.832,73.893,41.763,100.823l16.971-16.971   C36.335,209.874,24,180.095,24,148.419S36.335,86.964,58.733,64.566z" fill="#91DC5A"/><path d="M82.137,81.969c-17.75,17.748-27.525,41.348-27.525,66.45s9.775,48.702,27.525,66.45l16.971-16.971   c-13.218-13.216-20.496-30.788-20.496-49.479s7.278-36.264,20.496-49.48L82.137,81.969z" fill="#91DC5A"/><path d="M255.075,47.596l-16.971,16.971c22.399,22.397,34.733,52.177,34.733,83.853s-12.335,61.455-34.733,83.852l16.971,16.971   c26.931-26.931,41.763-62.737,41.763-100.823S282.006,74.526,255.075,47.596z" fill="#91DC5A"/><path d="M214.701,81.969L197.73,98.939c13.218,13.216,20.496,30.788,20.496,49.48s-7.278,36.264-20.496,49.479l16.971,16.971   c17.75-17.748,27.525-41.348,27.525-66.45S232.451,99.717,214.701,81.969z" fill="#91DC5A"/><path d="M148.586,114.789c-8.607,0-17.212,3.284-23.78,9.851c-13.131,13.133-13.131,34.424,0,47.559   c6.568,6.566,15.174,9.851,23.78,9.851c8.606,0,17.212-3.284,23.779-9.851c13.131-13.135,13.131-34.426,0-47.559   C165.798,118.073,157.192,114.789,148.586,114.789z M155.395,155.228c-2.454,2.454-5.319,2.821-6.809,2.821   c-1.489,0-4.356-0.367-6.808-2.818c-3.755-3.756-3.755-9.867-0.003-13.619c2.455-2.455,5.321-2.822,6.811-2.822   c1.489,0,4.354,0.367,6.808,2.82C159.147,145.363,159.147,151.475,155.395,155.228z" fill="#91DC5A"/></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg> \')';
        
        document.getElementById("mydiv").style.backgroundImage =myimg ;  
        
        
        
        //changing color according to theme .. new theme color :#424242
        myimg=myimg.replace(/#91DC5A/g,"#424242");
       document.getElementById("mydiv").style.backgroundImage =myimg ; 
             div {

  background-size:5em;
  width:5em;
  height:5em;
  
}
<html>
<body>

    
    <div id="mydiv"></div>
<span style="font:14px sans-serif;padding:7px;color:#fff;background:#689d94">
Target color</span>
   
  
    
</body>
</html>

【讨论】:

  • 必须是背景图片。
  • @RichardParnaby-King 还添加了背景图片案例.. 我会使用 z-index 来制作图片背景.. 无论如何.. 我已经为背景图片做了一个解决方法
  • svg 也可以用作背景图片。
  • Svgs 甚至可以单独用作网页。
【解决方案3】:

在这种情况下,关键是定义初始颜色。白色、黑色或任何灰度在技术上都是一种实际的颜色——你不能饱和或旋转它。您必须以某种方式对其进行“着色”,而棕褐色滤镜是唯一可以进行某种形式着色的滤镜。

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

让我们首先将白色图像变暗并应用棕褐色以获得我们可以使用的“基础”颜色:

filter: brightness(50%) sepia(1);

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

rgb(178, 160, 128)

第二步是convert that to HSL color-space,这给了我们:

hsl(38, 24.5%, 60%);

基色结果

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);
}
&lt;div&gt;&lt;/div&gt;

将基色转换为目标色

这两个第一步是静态的,每次我们需要找到目标调整时都会重复使用它的结果(sepia的实际值在SVG Filters specification中定义)。

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

hsl(170, 21.3%, 51.2%);

然后我们必须计算它们之间的差异。色调是通过简单地从目标中减去碱来计算的。饱和度和亮度相同,但由于我们假设 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%)

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

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

要设置它,假设 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;

请注意,由于 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%);
}
<div></div>
<span style="font:14px sans-serif;padding:7px;color:#fff;background:#689d94">
Target color</span>

可行的替代方案是:

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

【讨论】:

  • @K3N 我在这里有一个非常相似的问题:stackoverflow.com/questions/45901333/…。也许你有答案?谢谢!
  • 不幸的是,这个答案是错误的。它假设 hue-rotate 在 HSL 空间中运行。它不是。 CSS hue-rotate 基于 SVG Filter 规范中定义的底层 hue-rotate - 它没有 HSL 颜色空间的概念。糟糕的结果不是浮点近似的结果,而是色调旋转确实对颜色进行了野蛮数量的裁剪 - 特别是那些“极端” - 具有高度不等量的 R/G/B。
  • 这是一个不错的尝试,但完全具有误导性。
  • 这个答案是错误的! @Michael Mullany 的那个是正确的,并且工作完美,你甚至可以设置 alpha 通道。
猜你喜欢
  • 1970-01-01
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 2017-12-30
  • 2023-04-10
  • 2010-10-20
  • 2023-03-14
相关资源
最近更新 更多