Цвет уложенных полупрозрачных коробок зависит от заказа? - PullRequest
0 голосов
/ 29 мая 2018

Почему окончательный цвет двух сложенных полупрозрачных коробок зависит от заказа?

Как сделать так, чтобы в обоих случаях я получал одинаковый цвет?

.a {
  background-color: rgba(255, 0, 0, 0.5)
}

.b {
  background-color: rgba(0, 0, 255, 0.5)
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>

Ответы [ 4 ]

0 голосов
/ 29 мая 2018

Вы смешиваете три цвета в следующем порядке:

  • rgba(0, 0, 255, 0.5) over (rgba(255, 0, 0, 0.5) over rgba(255, 255, 255, 1))
  • rgba(255, 0, 0, 0.5) over (rgba(0, 0, 255, 0.5) over rgba(255, 255, 255, 1))

И вы получите разные результаты.Это происходит потому, что цвет переднего плана смешивается с цветом фона, используя нормальный режим смешивания 1 , который не является коммутативным .И поскольку он не является коммутативным, замена цветов переднего плана и фона приведет к разным результатам.

1 Режим смешивания - это функция, которая принимает цвет переднего плана и фона, применяет некоторую формулу и возвращает полученный результат.color.

Решение состоит в том, чтобы использовать режим смешивания, который является коммутативным: тот, который возвращает один и тот же цвет для той же пары цветов в любом порядке (например, режим многократного смешивания, который умножает оба цвета и возвращает полученный цветили режим затемнения смешивания, который возвращает более темный цвет двух).

$(function() {
  $("#mode").on("change", function() {
    var mode = $(this).val();
    $("#demo").find(".a, .b").css({
      "mix-blend-mode": mode
    });
  });
});
#demo > div {
  width: 12em;
  height: 5em;
  margin: 1em 0;
}

#demo > div > div {
  width: 12em;
  height: 4em;
  position: relative;
  top: .5em;
  left: 4em;
}

.a {
  background-color: rgba(255, 0, 0, 0.5);
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<select id="mode">
  <optgroup label="commutative">
    <option>multiply</option>
    <option>screen</option>
    <option>darken</option>
    <option>lighten</option>
    <option>difference</option>
    <option>exclusion</option>
  </optgroup>
  <optgroup label="non-commutative">
    <option selected>normal</option>
    <option>overlay</option>
    <option>color-dodge</option>
    <option>color-burn</option>
    <option>hard-light</option>
    <option>soft-light</option>
    <option>hue</option>
    <option>saturation</option>
    <option>color</option>
    <option>luminosity</option>
  </optgroup>
</select>

<div id="demo">
  <div class="a">
    <div class="b"></div>
  </div>
  <div class="b">
    <div class="a"></div>
  </div>
</div>

Для полноты приведем формулу для расчета составного цвета:

αs x (1 - αb) x Cs + αs x αb x B(Cb, Cs) + (1 - αs) x αb x Cb

с:

Cs: значение цвета для цвета переднего плана
αs: значение альфа для цвета переднего плана
Cb: значение цвета для цвета фона
αb: значение альфа для цвета фона B:функция смешивания

0 голосов
/ 29 мая 2018

Вы можете использовать свойство css, mix-blend-mode : multiply (ограничено поддержка браузера )

.a {
  background-color: rgba(255, 0, 0, 0.5);
  mix-blend-mode: multiply;
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
  mix-blend-mode: multiply;
}

.c {
  position: relative;
  left: 0px;
  width: 50px;
  height: 50px;
}

.d {
  position: relative;
  left: 25px;
  top: -50px;
  width: 50px;
  height: 50px;
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>

<div class="c a"></div>
<div class="d b"></div>

<div class="c b"></div>
<div class="d a"></div>
0 голосов
/ 29 мая 2018

Объяснение того, что происходит, см. В ответе Темани Афифа.
В качестве альтернативного решения вы можете взять один диапазон, например, a, расположить его и дать ему более низкий z-индекс, если он внутри b,Тогда укладка всегда будет одинаковой: b рисуется поверх a в первой строке, а a рисуется под b во второй.

.a {
  background-color: rgba(255, 0, 0, 0.5);
}

.b {
  background-color: rgba(0, 0, 255, 0.5);
}

.b .a {position:relative; z-index:-1;}
<span class="a"><span class="b">     Color 1</span></span>
<span class="b"><span class="a">Same Color 2</span></span>
0 голосов
/ 29 мая 2018

Просто потому, что в обоих случаях комбинация цветов не одинакова из-за того, как непрозрачность слоя top влияет на цвет слоя bottom .

В первом случае вы видите 50% синего и 50% прозрачного в верхнем слое.Через прозрачную часть вы видите 50% красного цвета в нижнем слое (таким образом, мы видим только 25% красного всего).Та же логика для второго случая ( 50% красного и 25% синего );Таким образом, вы увидите разные цвета, потому что в обоих случаях у нас не одинаковые пропорции.

Чтобы избежать этого, вам нужно иметь одинаковую пропорцию для обоих ваших цветов.

Вот пример, чтобы лучше проиллюстрировать и показать, как мы можем получить один и тот же цвет:

Inверхний слой (внутренний диапазон) имеет непрозрачность 0.25 (таким образом, у нас 25% первого цвета и 75% прозрачности), а затем для нижнего слоя (внешнего диапазона) мы имеем непрозрачность 0.333 (поэтому мыиметь 1/3 от 75% = 25% цвета, а остальное прозрачно).У нас одинаковая пропорция в обоих слоях (25%), поэтому мы видим одного цвета , даже если мы изменим порядок слоев.

.a {
  background-color: rgba(255, 0, 0, 0.333)
}

.b {
  background-color: rgba(0, 0, 255, 0.333)
}

.a > .b {
  background-color: rgba(0, 0, 255, 0.25)
}
.b > .a {
  background-color: rgba(255, 0, 0, 0.25)
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>

В качестве примечания, белый фон также влияет на отображение цветов.Его доля составляет 50%, что дает логический результат 100% (25% + 25% + 50%).

Вы также можете заметить, что невозможно иметь одинаковую пропорцию для обоих наших цветовесли у верхнего слоя непрозрачность больше 0.5, потому что у первого будет более 50% , а у второго он останется менее 50%:

.a {
  background-color: rgba(255, 0, 0, 1) /*taking 40% even with opacity:1*/
}

.b {
  background-color: rgba(0, 0, 255, 1) /*taking 40% even with opacity:1*/
}

.a > .b {
  background-color: rgba(0, 0, 255, 0.6) /* taking 60%*/
}
.b > .a {
  background-color: rgba(255, 0, 0, 0.6) /* taking 60%*/
}
<span class="a"><span class="b">          Color 1</span></span>
<span class="b"><span class="a">Different Color 2</span></span>

Обычный тривиальный случай - это когда верхний слой имеет opacity:1, что делает верхний цвет с пропорцией 100%;таким образом, это непрозрачный цвет.


Для более точного и точного объяснения здесь приведена формула, используемая для расчета цвета, который мы видим после комбинации обоих слоев ref :

ColorF = (ColorT*opacityT + ColorB*OpacityB*(1 - OpacityT)) / factor

ColorF - наш окончательный цвет. ColorT / ColorB - соответственно верхний и нижний цвета. opacityT / opacityB - соответственно верхняя и нижняя непрозрачности, определенные для каждого цвета:

factor определяется по этой формуле OpacityT + OpacityB*(1 - OpacityT).

Понятно, что если мы переключим два слоя, factor не изменится (он останется постоянным), но мы ясно увидим, что пропорция для каждого цвета изменится, поскольку у нас нет одинакового множителя.

Для нашего начального случая обе непрозрачности равны 0.5, поэтому у нас будет:

ColorF = (ColorT*0.5 + ColorB*0.5*(1 - 0.5)) / factor

Как объяснено выше, верхний цвет имеет пропорцию 50% (0.5) инижняя имеет пропорцию 25% (0.5*(1-0.5)), поэтому переключение слоев также изменит эти пропорции;таким образом, мы видим другой окончательный цвет.

Теперь, если мы рассмотрим второй пример, у нас будет:

ColorF = (ColorT*0.25 + ColorB*0.333*(1 - 0.25)) / factor

В этом случае у нас есть 0.25 = 0.333*(1 - 0.25), поэтому переключениедва слоя не будут иметь никакого эффекта;таким образом, цвет останется прежним.

Мы также можем четко определить тривиальные случаи:

  • Когда верхний слой имеет opacity:0, формула равна ColorF = ColorB
  • Когда верхний слой имеет opacity:1, формула равна ColorF = ColorT
...