我在数学方面取得了一些进展,但它们并不美观。理想情况下,我认为任何颜色最多可以用以下CSS滤镜表示:
(-webkit-)filter: contrast(0) sepia(1) hue-rotate(X) saturate(Y) brightness(Z);
换句话说,理想情况下,我们应该能够将任何颜色表示为相对于杏仁灰色 (
#AC9977
) 的色调、饱和度和亮度坐标。
虽然我还没有找到实现这一点的方法(也不确定是否可能),但我成功地制作了一个可以接受任何纯色(R、G、B、C、M、Y)或任何中性颜色(白色、黑色和灰色)的实现。其中有一些是优化过的(例如,黑色只是
brightness(0)
)。此外,如果您指定的颜色具有透明度,那么透明度将被添加为
opacity
滤镜。
目前这是代码(使用
LESS 编写):
// Filter prefixer.
.filter(@filters) { -webkit-filter+_: @filters; filter+_: @filters; }
// Helper that conditionally adds opacity filter when color calls for it.
._conditional-opacity(@color) when (alpha(@color) < 1) {
.filter(round(opacity(alpha(@color)), 3));
}
// Helper that adds a brightness filter when necessary.
._conditional-brightness(@channel) when (@channel < 255) {
.filter(brightness(round(@channel / 255, 3)));
}
// Special case for pure black.
.colorize(@color) when (fade(@color, 100
.filter(brightness(0));
._conditional-opacity(@color);
}
// Special case for pure grey and off-by-one-grey.
.colorize(@color) when (fade(@color, 100
(fade(@color, 100
.filter(contrast(0));
._conditional-opacity(@color);
}
// Special case for shades of pure red.
.colorize(@color) when (red(@color) > 0)
and (green(@color) = 0)
and (blue(@color) = 0) {
.filter(contrast(0) sepia(1) saturate(999));
._conditional-brightness(red(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure green.
.colorize(@color) when (red(@color) = 0)
and (green(@color) > 0)
and (blue(@color) = 0) {
.filter(contrast(0) sepia(1) hue-rotate(99deg) saturate(999));
._conditional-brightness(green(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure blue.
.colorize(@color) when (red(@color) = 0)
and (green(@color) = 0)
and (blue(@color) > 0) {
.filter(contrast(0) sepia(1) hue-rotate(199deg) saturate(999));
._conditional-brightness(blue(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure cyan.
.colorize(@color) when (red(@color) = 0)
and (green(@color) > 0)
and (blue(@color) = green(@color)) {
.filter(contrast(0) sepia(1) invert(1) saturate(999));
._conditional-brightness(blue(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure magenta.
.colorize(@color) when (red(@color) = blue(@color))
and (green(@color) = 0)
and (blue(@color) > 0) {
.filter(contrast(0) sepia(1) hue-rotate(-99deg) saturate(999));
._conditional-brightness(red(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure yellow.
.colorize(@color) when (red(@color) > 0)
and (green(@color) = red(@color))
and (blue(@color) = 0) {
.filter(contrast(0) sepia(1) hue-rotate(199deg) saturate(999) invert(1));
._conditional-brightness(green(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure grey and white.
.colorize(@color) when (red(@color) = green(@color))
and (green(@color) = blue(@color))
and not (blue(@color) = 0) // We've optimized these before.
and not (blue(@color) = 127)
and not (blue(@color) = 128) {
.filter(contrast(0) brightness(round(blue(@color) / 255 * 2 + .00765, 3)));
._conditional-opacity(@color);
}
.colorize(@color) when (default()) {
// General case not figured out yet.
}
如果你想尝试一下,
这里有一个CodePen(它可以自动编译LESS)。
请注意,这仅仅是不够完美的。如果你提供了更好的答案(包括使用其他方法解决问题),我可能会接受你的答案,而不是选择我的答案,除非我的答案能代表任何给定的颜色(目前无法实现;我可能已经放弃了)。
#729FCF
)组成,同时保留alpha通道。例如,考虑一个用SVG表示的图标,它最初是白色的,您希望它变成不同情况下的某种红色或绿色。我可以更多或少地“眼测”颜色,但我正在尝试制作一些可重复使用且不需要猜测的东西,在我对颜色的基本理解中,我已经制作了一个似乎不起作用的算法。 - Camilo Martin