Как вы имитируете эффект непрозрачности на элементе, не делая его прозрачным? - PullRequest
1 голос
/ 04 октября 2019

Я хочу, чтобы у div был "серый" вид, который вы видите с filter:opacity(0.5) на белом фоне, но я не хочу на самом деле сделать его прозрачным. Как мне это сделать? Я знаю, что одним из решений было бы просто поместить другой элемент с белым фоном позади него, но я ищу более простое решение с использованием только эффектов фильтра CSS.

Ответы [ 2 ]

2 голосов
/ 04 октября 2019

Установка контрастности на 1/3 и яркости на 1,5 имитирует непрозрачность 0,5. В демонстрации второй тестовый шаблон имеет непрозрачность 0,5, но при наведении на него курсора он переключается на альтернативный фильтр, и из неперекрывающейся области видно, что цвета точно одинаковы,по крайней мере, насколько может судить человеческое зрение.

Я не совсем уверен, каковы здесь отношения. Если вы хотите смоделировать непрозрачность 0,25, то вы можете ожидать, что сработает контрастность 1/6 и яркость 1,75, и это близко, но есть слабые изменения. Это не так точно, как для 0,5 непрозрачности.

img {
  position: absolute;
}

#img1 {
  top: 0px;
  left: 0px;
}

#img2 {
  top: 40px;
  left: 84px;
  filter: opacity(0.5);
  
}


#img2:hover {
  filter: contrast(calc(1/3)) brightness(1.5);
}
<img id="img1" height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
<img id="img2" height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
1 голос
/ 04 октября 2019

Я собираюсь объяснить математику за ответом @ codebreaker и попытаться дать общую формулу. Я буду опираться на предыдущий ответ , где я определил формулу некоторых функций фильтра.

У нас есть f(x) = p*(x - 255/2) + 255/2 для contrast(p) и f(x) = x*p для brightness(p)

Чтобы получить contrast(p1) brightness(p2), мы смешиваем обе функции

f(x) = p2*(p1*(x - 255/2) + 255/2)

Упростим до

f(x) = p1*p2(*x - 127.5) + p2*127.5

Теперь для opacity(p) у нас есть ref

f(x) =  x*p + C*(1 - p)

Где C - цвет фона изображения, и в вашем случае вы рассматривали белый, поэтому мы можем заменить его на 255, чтобы получить

f(x) =  x*p + 255*(1 - p) = p*(x - 255) + 255

Сейчасмы просто хотим, чтобы обе функции (непрозрачность и контрастность) были одинаковыми, поэтому мы можем написать

p1*p2*(x - 127.5) + p2*127.5 = p*(x - 255) + 255

Для p=0.5, p1=1/3, p2=1.5=3/2 у нас будет

1/2*(x - 127.5) + 3/2*127.5 = 1/2*(x - 255) + 255
1/2*x - 127.5/2 + 3/2*127.5 = 1/2*x + 127.5
...
0 = 0

Это объясняет связь между значениями, которые вы используете. Вы также можете найти любую другую комбинацию значений, которую вы хотите.

Для общего случая мы можем рассмотреть:

p1*p2*(x - 127.5) + p2*127.5 = p*(x - 255) + 255
x*(p1*p2 - p) + p2*127.5*(1 - p1) + p*255 - 255 = 0

У нас должно быть (p1*p2 - p) = 0 и p2*127.5*(1 - p1) + p*255 - 255 = 0, поэтому мы получим

p1*p2 = p
p2*(1 - p1) = (1 - p)*2

и, наконец,

p2 = 2 - p
p1 = p/(2 - p)

Если мы рассмотрим непрозрачность 0.25, у нас будет:

p2 = 1.75
p1 = 1/7

img:first-of-type {
  filter: opacity(var(--o,1));
}

img:last-of-type {
  filter: contrast(calc(var(--o,1)/(2 - var(--o,1)))) brightness(calc(2 - var(--o,1)));
}
<div>
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
</div>

<div style="--o:0.75">
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
</div>

<div style="--o:0.5">
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
</div>

<div style="--o:0.25">
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
  <img  height="126" width="168" src="https://upload.wikimedia.org/wikipedia/commons/6/66/SMPTE_Color_Bars.svg">
</div>
...