Скажем, у меня есть цвет фона, поверх которого проходит «лента» другого сплошного цвета. Теперь я хочу, чтобы лента была частично прозрачной, чтобы некоторые детали переходили сквозь нее, но при этом сохраняла «тот же цвет» на фоне ленты.
Есть ли способ (легко) определить, для данной непрозрачности / альфа <100% цвета ленты, какие значения RGB должны быть идентичны ее цвету со 100% непрозрачностью по фону?
Вот картинка. Фон есть rgb(72, 28, 97)
, лента rgb(45, 34, 70)
. Я хочу, rgba(r, g, b, a)
чтобы лента была идентична этому сплошному цвету.
Ответы:
Смешивание цветов - это просто линейная интерполяция на канал, верно? Итак, математика довольно проста. Если у вас RGBA1 вместо RGB2, эффективный визуальный результат RGB3 будет:
… Где альфа-канал находится в диапазоне от 0,0 до 1,0.
Проверка работоспособности: если альфа равна 0, является ли RGB3 таким же, как RGB2? Да. Если альфа равна 1, является ли RGB3 таким же, как RGB1? Да.
Если вы заблокировали только цвет фона и конечный цвет, существует большое количество цветов RGBA (бесконечное, в пространстве с плавающей запятой), которые могут удовлетворить требования. Таким образом, вам нужно выбрать либо цвет полосы, либо желаемый уровень непрозрачности и узнать значение другого.
Выбор цвета на основе альфа
Если вы знаете RGB3 (окончательный желаемый цвет), RGB2 (цвет фона) и A1 (желаемую степень непрозрачности), и вы просто ищете RGB1, то мы можем переупорядочить уравнения следующим образом:
Есть некоторые цветовые комбинации, которые теоретически возможны, но невозможны в стандартном диапазоне RGBA. Например, если фон чистый черный, желаемый воспринимаемый цвет - чистый белый, а желаемая альфа составляет 1%, тогда вам потребуются:
r1 = g1 = b1 = 255/0.01 = 25500
… Сверхяркий белый цвет в 100 раз ярче, чем любой другой.
Выбор альфы на основе цветов
Если вы знаете RGB3 (окончательный желаемый цвет), RGB2 (цвет фона) и RGB1 (цвет, который у вас есть, непрозрачность которого вы хотите изменить), и вы просто ищете A1, то мы можем изменить расположение уравнения таким образом:
Если они дают разные значения, вы не можете добиться точного совпадения, но вы можете усреднить альфы, чтобы получить как можно более близкие значения. Например, в мире нет прозрачности, которая позволила бы вам поставить зеленый поверх красного, чтобы получить синий.
источник
r1
,g1
иb1
тоже неизвестно?Я сделал МЕНЬШЕ миксина, используя ответ 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 «s и ephemer » s больших ответов, здесь есть функция 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); }
Я только что протестировал его с рядом комбинаций (все темы Bootswatch), и он отлично работает как для результатов «темнота на свету», так и «свет на темноте».
PS: если вам нужна точность лучше, чем ± 1/256 в результирующем цвете, вам нужно будет знать, какой алгоритм округления применяют браузеры при смешивании цветов rgba (я не знаю, стандартизован это или нет), и добавить подходящий состояние к существующему
@while
, чтобы оно продолжало увеличиваться,$alpha
пока не достигнет желаемой точности.источник
transparentify()
: stylus-lang.com/docs/bifs.html#transparentifytop-bottom-alpha ... которую я обнаружил после переноса ее вручную на Stylus ...Из ответа @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 не дает решения (очевидно).источник
Самое практичное решение, которое я нашел до сих пор: просто измерьте полученный цвет с помощью инструмента выбора цвета, а затем используйте измеренный цвет для наложения. Этот метод обеспечивает идеальное соответствие цвета.
Я пробовал использовать разные миксины, но из-за ошибки округления я все еще мог видеть разницу невооруженным глазом
источник
Чтобы расширить ответ @ Tobia и позволить указать непрозрачность, больше похожую на прозрачность:
@function rgbaMorph($desired-color, $background-color: rgb(255,255,255), $desired-alpha: 0) { $r1: red($desired-color); $g1: green($desired-color); $b1: blue($desired-color); $r2: red($background-color); $g2: green($background-color); $b2: blue($background-color); $r: -1; $g: -1; $b: -1; @if ($desired-alpha != 0) { $r: ( $r1 - $r2 + ($r2 * $desired-alpha) ) / $desired-alpha; $g: ( $g1 - $g2 + ($g2 * $desired-alpha) ) / $desired-alpha; $b: ( $b1 - $b2 + ($b2 * $desired-alpha) ) / $desired-alpha; } @if (($desired-alpha == 0) or ($r < 0 or $g < 0 or $b < 0 or $r > 255 or $g > 255 or $b > 255)) { //if alpha not attainable, this will find lowest alpha that is $alpha: $desired-alpha; @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: $r1 * $inv + $r2 * (1 - $inv); $g: $g1 * $inv + $g2 * (1 - $inv); $b: $b1 * $inv + $b2 * (1 - $inv); } @debug "Color not attainable at opacity using alpha: " $alpha " instead of: " $desired-alpha; $desired-alpha: $alpha; } @return rgba($r, $g, $b, $desired-alpha); }
источник