Digamos que tengo un color de fondo con una "cinta" que lo recorre en otro color sólido. Ahora, quiero que la cinta sea parcialmente transparente para permitir que algunos detalles se mezclen, pero aún así mantener la cinta del "mismo color" sobre el fondo.
¿Hay alguna manera de determinar (fácilmente), para una opacidad dada / alfa <100% del color de la cinta, qué valores RGB debería tener para ser idéntico a su color con un 100% de opacidad sobre el fondo?
Aquí tienes una foto. El fondo es rgb(72, 28, 97)
, cinta rgb(45, 34, 70)
. Quiero una rgba(r, g, b, a)
para la cinta para que parezca idéntica a este color sólido.
Respuestas:
La combinación de colores es solo una interpolación lineal por canal, ¿verdad? Entonces las matemáticas son bastante simples. Si tiene RGBA1 sobre RGB2, el resultado visual efectivo RGB3 será:
… Donde el canal alfa es de 0.0 a 1.0.
Comprobación de cordura: si el alfa es 0, ¿RGB3 es lo mismo que RGB2? Si. Si el alfa es 1, ¿RGB3 es lo mismo que RGB1? Si.
Si bloqueó solo el color de fondo y el color final, hay una gran cantidad de colores RGBA (infinitos, en el espacio de punto flotante) que podrían satisfacer los requisitos. Por lo tanto, debe elegir el color de la barra o el nivel de opacidad que desee y averiguar el valor de la otra.
Elegir el color basado en Alpha
Si conoce RGB3 (el color final deseado), RGB2 (el color de fondo) y A1 (cuánta opacidad desea), y solo está buscando RGB1, entonces podemos reorganizar las ecuaciones de la siguiente manera:
Hay algunas combinaciones de colores que son teóricamente posibles, pero imposibles dado el rango estándar de RGBA. Por ejemplo, si el fondo es negro puro, el color percibido deseado es blanco puro y el alfa deseado es 1%, entonces necesitaría:
r1 = g1 = b1 = 255/0.01 = 25500
… Un blanco superbrillante 100 veces más brillante que cualquier otro disponible.
Elegir el Alfa en función de los colores
Si conoce RGB3 (el color final deseado), RGB2 (el color de fondo) y RGB1 (el color que tiene del que desea variar la opacidad), y solo está buscando A1, entonces podemos reorganizar el ecuaciones así:
Si estos dan valores diferentes, entonces no puede hacer que coincida exactamente, pero puede promediar los valores alfa para acercarse lo más posible. Por ejemplo, no hay opacidad en el mundo que le permita poner verde sobre rojo para obtener azul.
fuente
r1
,g1
yb1
también se desconoce?Hice un mixin MENOS usando la respuesta de Phrogz. usted ingresa:
Aquí está el código:
.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); }
Uso así:
@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); }
Obviamente, no funciona para combinaciones imposibles (como lo menciona Phrogz), eso significa que solo se admiten niveles leves de transparencia. Vea cómo le va.
fuente
Gracias a Phrogz 's y Ephemer ' s grandes respuestas, aquí es una función que SASS automagicamente calcula el mejor color RGBA equivalente.
Lo llama con el color deseado y el fondo existente, y calculará el mejor color RGBA equivalente (es decir, el más transparente) que dé el resultado deseado dentro de ± 1/256 de cada componente RGB (debido a errores de redondeo):
@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); }
Lo probé con una serie de combinaciones (todos los temas de Bootswatch) y funciona de maravilla, tanto para resultados de oscuridad sobre luz como de luz sobre oscuridad.
PD: Si necesita una precisión superior a ± 1/256 en el color resultante, necesitará saber qué tipo de algoritmo de redondeo aplican los navegadores al mezclar colores rgba (no sé si eso está estandarizado o no) y agregar un condición a la existente
@while
, de manera que siga aumentando$alpha
hasta lograr la precisión deseada.fuente
transparentify()
: stylus-lang.com/docs/bifs.html#transparentifytop-bottom-alpha ... que descubrí después de portar esto manualmente a Stylus ...De la respuesta de @Phrogz:
r3 = r2 + (r1-r2)*a1 g3 = g2 + (g1-g2)*a1 b3 = b2 + (b1-b2)*a1
Entonces:
r3 - r2 = (r1-r2)*a1 g3 - g2 = (g1-g2)*a1 b3 - b2 = (b1-b2)*a1
Entonces:
r1 = (r3 - r2) / a1 + r2 g1 = (g3 - g2) / a1 + g2 b1 = (b3 - b2) / a1 + b2
Nota usted puede elegir cualquier valor de
a1
, y esto va a encontrar los valores correspondientes der1
,g1
yb1
requeridos. Por ejemplo, elegir un alfa de 1 te dice que necesitas RGB1 = RGB3, pero elegir un alfa de 0 no da ninguna solución (obviamente).fuente
La solución más práctica que encontré hasta ahora: simplemente mida el color resultante con una herramienta de selección de color y luego use el color medido para la superposición. Este método proporciona una combinación de colores perfecta.
Intenté usar diferentes mezclas, pero debido a un error de redondeo, aún pude ver la diferencia a simple vista.
fuente
Para expandir la respuesta de @ Tobia y permitir especificar la opacidad más como transparente:
@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); }
fuente