Поиск "эквивалентного" цвета с непрозрачностью
скажем, у меня есть цвет фона с "лентой", бегущей по нему в другом сплошном цвете. Теперь я хочу, чтобы лента была частично прозрачной, чтобы некоторые детали смешивались, но все же сохраняли ленту "того же цвета" на фоне.
есть ли способ (легко) определить, для заданной непрозрачности/Альфа
вот картинка. Фон rgb(72, 28, 97)
, лента rgb(45, 34, 70)
. Я хочу rgba(r, g, b, a)
для ленты, чтобы она выглядела идентично этому сплошному цвету.
4 ответа:
смешивание цветов - это просто линейная интерполяция на канал, верно? Математика довольно простая. Если у вас есть RGBA1 над RGB2, эффективный визуальный результат RGB3 будет:
r3 = r2 + (r1-r2)*a1 g3 = g2 + (g1-g2)*a1 b3 = b2 + (b1-b2)*a1
...где альфа-канал от 0.0 до 1.0.
проверка здравомыслия: если Альфа равна 0, является ли RGB3 таким же, как RGB2? Да. Если Альфа равна 1, является ли RGB3 таким же, как RGB1? Да.
если вы закрыли только цвет фона и цвет, есть большой количество цветов RGBA (бесконечное, в пространстве с плавающей запятой), которые могут удовлетворить требованиям. Таким образом, вы должны выбрать либо цвет панели, либо уровень непрозрачности, который вы хотите, и узнать значение другого.
выбор цвета на основе альфа
если вы знаете RGB3 (конечный желаемый цвет), RGB2 (цвет фона) и A1 (сколько непрозрачности вы хотите), и вы просто ищете RGB1, то мы можем перестроить уравнения таким образом:
r1 = (r3 - r2 + r2*a1)/a1 g1 = (g3 - g2 + g2*a1)/a1 b1 = (b3 - b2 + b2*a1)/a1
есть некоторые цветовые комбинации, которые теоретически возможны, но невозможны, учитывая стандартный диапазон RGBA. Например, если фон чисто черный, желаемый воспринимаемый цвет чисто белый, а желаемый альфа-1%, то вам понадобится:
r1 = g1 = b1 = 255/0.01 = 25500
...супер-яркий белый 100× ярче, чем любой доступный.
выбор Альфа на основе цветов
если вы знаете RGB3 (the окончательный желаемый цвет), RGB2 (цвет фона) и RGB1 (цвет, который у вас есть, который вы хотите изменить непрозрачность), и вы просто ищете A1, тогда мы можем перестроить уравнения таким образом:
a1 = (r3-r2) / (r1-r2) a1 = (g3-g2) / (g1-g2) a1 = (b3-b2) / (b1-b2)
если они дают разные значения, то вы не можете сделать его точно соответствовать, но вы можете усреднить Альфы, чтобы получить как можно ближе. Например, в мире нет непрозрачности, которая позволит вам поставить зеленый над Красным, чтобы получить синий.
Я сделал меньше смешивания, используя ответ Phrogz. вы вводите:
- как должен выглядеть цвет
- С определенной Альфой
- на заданном фоне (по умолчанию белый)
вот код:
.bg_alpha_calc (@desired_colour, @desired_alpha, @background_colour: white) { @r3: red(@desired_colour); @g3: green(@desired_colour); @b3: blue(@desired_colour); @r2: red(@background_colour); @g2: green(@background_colour); @b2: blue(@background_colour); // r1 = (r3 - r2 + r2 * a1) / a1 @r1: ( @r3 - @r2 + (@r2 * @desired_alpha) ) / @desired_alpha; @g1: ( @g3 - @g2 + (@g2 * @desired_alpha) ) / @desired_alpha; @b1: ( @b3 - @b2 + (@b2 * @desired_alpha) ) / @desired_alpha; background-color: @desired_colour; background-color: rgba(@r1, @g1, @b1, @desired_alpha); }
использование так:
@mycolour: #abc; @another_colour: blue; .box_overlay { // example: .bg_alpha_calc (@mycolour, 0.97, @another_colour); // or (for white bg) just: .bg_alpha_calc (@mycolour, 0.97); }
очевидно, не работает для невозможных комбинаций (как упоминалось Phrogz), это означает, что поддерживаются только умеренные уровни прозрачности. Посмотрим, как ты справишься с этим.
спасибо Phrogzи эфемеровыеотличные ответы, вот функция SASS, которая автоматически вычисляет лучший эквивалентный цвет RGBA.
вы вызываете его с желаемым цветом и существующим фоном, и он вычислит лучший (то есть самый прозрачный) эквивалентный цвет RGBA, который дает желаемый результат в пределах ±1/256 каждого компонента RGB (из-за ошибок округления):
@function alphaize($desired-color, $background-color) { $r1: red($background-color); $g1: green($background-color); $b1: blue($background-color); $r2: red($desired-color); $g2: green($desired-color); $b2: blue($desired-color); $alpha: 0; $r: -1; $g: -1; $b: -1; @while $alpha < 1 and ($r < 0 or $g < 0 or $b < 0 or $r > 255 or $g > 255 or $b > 255) { $alpha: $alpha + 1/256; $inv: 1 / $alpha; $r: $r2 * $inv + $r1 * (1 - $inv); $g: $g2 * $inv + $g1 * (1 - $inv); $b: $b2 * $inv + $b1 * (1 - $inv); } @return rgba($r, $g, $b, $alpha); }
Я только что протестировал его против a количество комбинаций (все темы Bootswatch), и это работает удовольствие, как для темных-на-свету, так и для светлых-на-темных результатов.
PS: Если вам нужно лучше, чем точность ±1/256 в результирующем цвете, вам нужно будет знать, какой алгоритм округления браузеров применяется при смешивании цветов rgba (я не знаю, если это стандартизировано или нет) и добавить подходящее условие к существующему
@while
, Так что он продолжает расти$alpha
до достижения требуемой точности.
от @Phrogz ' ответ:
r3 = r2 + (r1-r2)*a1 g3 = g2 + (g1-g2)*a1 b3 = b2 + (b1-b2)*a1
так:
r3 - r2 = (r1-r2)*a1 g3 - g2 = (g1-g2)*a1 b3 - b2 = (b1-b2)*a1
так:
r1 = (r3 - r2) / a1 + r2 g1 = (g3 - g2) / a1 + g2 b1 = (b3 - b2) / a1 + b2
Примечание Вы можете выбрать любое значение
a1
, и это будет найти соответствующие значенияr1
,g1
иb1
требуются. Например, выбор Альфа 1 говорит вам, что вам нужно RGB1 = RGB3, но выбор Альфа 0 не дает решения (очевидно).