У меня есть значок, цвет которого я хотел бы изменить с помощью CSS. Он находится в оптимизированном для данных SVG, встроенном в CSS.
Обычно это невозможно. Вот почему были изобретены иконочные шрифты; их основное преимущество перед SVG заключается в возможности получать правила color
и text-shadow
из CSS. Итак, CSS-фильтры теперь могут делать обе вещи для произвольные изображения и теперь они работают во всех браузерах Blink, Webkit и Gecko, и можно ожидать от будущего IE/Spartan.
Замена text-shadow
проста; просто используйте фильтр drop-shadow
.
Однако окрашивание изображения в определенный цвет оказалось очень сложным, несмотря на наличие всех необходимых фильтров. Моя теория до сих пор такова:
- Используйте
contrast(0)
, чтобы превратить все изображение в сплошной серый, сохраняя при этом альфа-канал (вики Mozilla говорит, что он станет черным, но во всех браузерах он становится серым, должно быть, это опечатка). - Используйте
sepia(1)
, так как мы не можем работать с оттенок/насыщенность серого изображения. Это гарантирует, что все изображение состоит из эталонного цвета, с которым мы можем выполнять математические операции; в частности,#AC9977
.
На этом этапе мы должны иметь возможность превратить все изображение из сплошного #AC9977
в любой желаемый цвет с помощью hue-rotate
, saturate
и brightness
.
Во-первых, какие цветовые координаты используют браузеры? Мне не удалось найти смысл в спецификации, чтобы убедиться, что она использует HSL (Легкость) или HSV (Значение), но поскольку HSB (Яркость) — это другое название HSV, я полагаю, что он использует HSV. Кроме того, использование чего-то вроде brightness(999)
насыщает цвета (вместо того, чтобы делать их белыми), что происходит в HSV, но не в HSL.
Исходя из этого предположения, мы будем действовать следующим образом:
- Вычислите разницу оттенков между
#AC9977
и цветом, который нам нужен, и используйтеhue-rotate
. - Рассчитайте разницу насыщенности между обоими и используйте
saturate
а>. - Рассчитайте разницу в яркости между ними и используйте
brightness
а>.
Поскольку это не то, что нужно делать вручную, мы будем использовать препроцессор LESS:
.colorize(@color) {
@sepiaGrey: #AC9977;
@hOffset: (hsvhue(@color) - hsvhue(@sepiaGrey)) * 1deg;
@sRatio: unit(hsvsaturation(@color) / hsvsaturation(@sepiaGrey));
@vRatio: unit(hsvvalue(@color) / hsvvalue(@sepiaGrey));
-webkit-filter: contrast(0) sepia(1) hue-rotate(@hOffset) saturate(@sRatio) brightness(@vRatio);
filter: contrast(0) sepia(1) hue-rotate(@hOffset) saturate(@sRatio) brightness(@vRatio);
}
Это, в моем понимании, должно работать. Но это не так. Почему и как заставить это работать?
Пример того, чего я пытаюсь достичь
Рассматривайте значок как изображение или элемент (фоновое изображение, форма на основе CSS и т. д.) с любым цветом и формой, определяемой прозрачностью (не прямоугольное изображение, которое можно просто наложить друг на друга). Я хочу, чтобы он полностью состоял из определенного цвета с помощью CSS (предположительно, с использованием filters
).
Я планирую реализовать это как LESS mixin, который принимает аргумент цвета, но просто достаточно руководства по логике функций HSB.
#729FCF
), сохраняя при этом альфа-канал. Например, рассмотрим значок, представленный в SVG, который изначально белый, и вы хотите, чтобы он приобрел оттенок красного или зеленого для разных случаев. В какой-то степени я могу более или менее оценить цвет на глаз, но я пытаюсь сделать что-то, что можно будет использовать повторно и не нужно догадываться, и в моем элементарном понимании цветов я создал алгоритм, который не кажется, работает. - person Camilo Martin   schedule 05.04.2015