【问题标题】:Why is hue-rotate(180deg) not its own inverse? [duplicate]为什么 hue-rotate(180deg) 不是它自己的逆? [复制]
【发布时间】:2022-02-05 05:10:59
【问题描述】:

The hue-rotate() filter function "旋转元素的色调...指定为角度"。如果这是真的,filter: hue-rotate(180deg) hue-rotate(180deg) 将无效。但它肯定确实有效果:

.square {
  height: 3rem;
  padding: 1rem;
  background: linear-gradient( 90deg, rgba(255, 0, 0, 1) 0%, rgba(255, 154, 0, 1) 10%, rgba(208, 222, 33, 1) 20%, rgba(79, 220, 74, 1) 30%, rgba(63, 218, 216, 1) 40%, rgba(47, 201, 226, 1) 50%, rgba(28, 127, 238, 1) 60%, rgba(95, 21, 242, 1) 70%, rgba(186, 12, 248, 1) 80%, rgba(251, 7, 217, 1) 90%, rgba(255, 0, 0, 1) 100%);
  font-family: monospace;
  font-weight: bold;
  color: white;
}

.double-invert {
  filter: hue-rotate(180deg) hue-rotate(180deg);
}
<div class="square">filter: none</div>
<div class="square double-invert">filter: hue-rotate(180deg) hue-rotate(180deg)</div>

这里发生了什么? hue-rotate 实际上是做什么的?以及如何实现 其自身逆向的色调旋转? (或者,我怎样才能想出一个反转色调旋转的滤镜?)

更新:按照 Temani Aiff 的回答,似乎 hue-rotate(180deg) 实际上是一个矩阵乘法。但是,尚不清楚它实际使用的是什么矩阵。下面显示我们可以将 SVG 过滤器 type="hueRotate" 重新实现为原始矩阵,但 CSS 过滤器 hue-rotate 实际上并不匹配其中任何一个:

.square {
  height: 3rem;
  padding: 1rem;
  background: linear-gradient( 90deg, rgba(255, 0, 0, 1) 0%, rgba(255, 154, 0, 1) 10%, rgba(208, 222, 33, 1) 20%, rgba(79, 220, 74, 1) 30%, rgba(63, 218, 216, 1) 40%, rgba(47, 201, 226, 1) 50%, rgba(28, 127, 238, 1) 60%, rgba(95, 21, 242, 1) 70%, rgba(186, 12, 248, 1) 80%, rgba(251, 7, 217, 1) 90%, rgba(255, 0, 0, 1) 100%);
  font-family: monospace;
  font-weight: bold;
  color: white;
}

.hue-rotate {
  filter: hue-rotate(180deg);
}

.hue-rotate-svg {
  filter: url(#svgHueRotate180);
}

.hue-rotate-svg-matrix {
  filter: url(#svgHueRotate180Matrix);
}
<svg style="position: absolute; top: -99999px" xmlns="http://www.w3.org/2000/svg">
  <filter id="svgHueRotate180">
    <feColorMatrix in="SourceGraphic" type="hueRotate"
        values="180" />
  </filter>
  
  <!-- Following matrix calculated following spec -->
  <filter id="svgHueRotate180Matrix">
    <feColorMatrix in="SourceGraphic" type="matrix"
        values="
-0.574 1.43  0.144 0 0
 0.426 0.43  0.144 0 0
 0.426 1.43 -0.856 0 0
 0     0     0     1 0" />
  </filter>
</svg>

<div class="square">filter: none</div>
<div class="square hue-rotate">filter: hue-rotate(180deg)</div>
<div class="square hue-rotate-svg">using SVG hueRotate</div>
<div class="square hue-rotate-svg-matrix">using SVG raw matrix</div>

至少在 Chrome 和 Firefox 中,hue-rotate 正在做一些不同于 SVG 过滤器的事情。但它在做什么?!

【问题讨论】:

  • 为什么不应该有效果?
  • @cloned 因为在普通几何中,这些旋转添加到单个旋转 360 度,相当于 0 度
  • 另外:因为如果hue-rotate(Xdeg)表示将hsl(h,s,l)转换为hsl(h+X, s, l),那么hue-rotate(180deg) hue-rotate(180deg)hsl(h,s,l)转换为hsl(h+360deg, s, l),相当于hsl(h,s,l)
  • 这可能是由于 rgbahsla 之间的转换而发生的,因为某些颜色无法正确转换。由于filter 值被逐一应用(下一个应用于前一个的结果),转换偏差变得更加严重。

标签: html css svg colors css-filters


【解决方案1】:

hue-rotate(X) hue-rotate(X) 不等于hue-rotate(X+X) 如下所示:

.square {
  height: 3rem;
  padding: 1rem;
  background: linear-gradient( 90deg, rgba(255, 0, 0, 1) 0%, rgba(255, 154, 0, 1) 10%, rgba(208, 222, 33, 1) 20%, rgba(79, 220, 74, 1) 30%, rgba(63, 218, 216, 1) 40%, rgba(47, 201, 226, 1) 50%, rgba(28, 127, 238, 1) 60%, rgba(95, 21, 242, 1) 70%, rgba(186, 12, 248, 1) 80%, rgba(251, 7, 217, 1) 90%, rgba(255, 0, 0, 1) 100%);
  font-family: monospace;
  font-weight: bold;
  color: white;
}

.single-invert {
  filter: hue-rotate(360deg);
}

.double-invert {
  filter: hue-rotate(180deg) hue-rotate(180deg);
}
<div class="square">filter: none</div>
<div class="square single-invert">filter: hue-rotate(360deg) </div>
<div class="square double-invert">filter: hue-rotate(180deg) hue-rotate(180deg)</div>

要了解,您需要深入研究数学公式。从the specificationhue-rotate() 是:

<filter id="hue-rotate">
  <feColorMatrix type="hueRotate" values="[angle]"/>
</filter>

对于feColorMatrix,我们有一个matrix calculation。我会在数学之后给你每个案例的矩阵(你可以按照规范自己尝试)

180deg

-0.574  1.43   0.144
 0.426  0.43   0.144
 0.426  1.43  -0.856  

对于360deg,它是单位矩阵

1 0 0
0 1 0
0 0 1

当您应用两个过滤器时,这意味着您将使用相同的矩阵两次,这只不过是一次矩阵乘法。所以你必须做下面的乘法:

|-0.574  1.43   0.144|    |-0.574  1.43   0.144|
| 0.426  0.43   0.144| x  | 0.426  0.43   0.144|
| 0.426  1.43  -0.856|    | 0.426  1.43  -0.856| 

得到:

1     8.326  -1.387
1.387 1       0
0     0       1

这不是身份,所以使用hue-rotate(180deg) 过滤两次并不等同于hue-rotate(360deg)。换句话说,不要将其视为“和”,而应将其视为“乘法”。

【讨论】:

  • 惊人的答案,谢谢!所以 MDN 文档具有误导性 - 它根本不是真正的“色调旋转”,而是对类似的东西的线性近似,它也保留了亮度......
  • 现在我剩下的困惑是 - 你给出的矩阵(我也从遵循规范中得到)实际上似乎没有给出相同的结果......我将更新我的问题以显示什么我的意思是
  • 我已经在问题的末尾添加了我的困惑 - 看起来你的答案是正确的,但是 Chrome 和 Firefox 正在做一些完全不同的事情......
  • @jameshfisher MDN 是正确的,规范也在这里说同样的话:w3.org/TR/filter-effects/#funcdef-filter-hue-rotate 但似乎我需要再次重新检查规范,因为我认为 SVG 过滤器会给出与CSS 过滤器这就是我使用 SVG 计算的原因,但可能与 CSS 实现有所不同
  • @jameshfisher:HSL 也是一个近似值:相同的 L 并不意味着相同的亮度。检查你在两个 sn-p 中的第一个乐队。它们看起来是不是一直很轻盈?蓝色和黄色?简而言之:它是 CPU(和低内存)中快速和可并行化与精确、复杂(您需要在定义上更加精确,您可能会在某些屏幕上得到惊喜等)的权衡,并且您需要用复杂的函数执行浮点运算)。在常用的 HSL 中,“hue”也有一个奇怪的度数含义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-23
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
相关资源
最近更新 更多