Получите RGB наложенных цветов (элементов)

Скажем, у меня есть следующая настройка

body {
    background: rgba(0,0,0,0.5);
}
#first {
    width: 200px;
    height: 100px;
    background: rgba(255,0,0,0.5);
}
#second {
    width: 50px;
    height: 50px;
    background: rgba(86, 185, 11, .5);
    position: absolute;
    top: 20px;
    left: 20px;
}

Как я могу получить / рассчитать цвет #second div?


Я сделал снимок экрана с div и проверил их RGB в Photoshop.

Body                 -> 128,128,128
First red div        -> 192,65,65
Second yellowish div -> 140,125,38

введите описание изображения здесь

Я нашел способ вычислить rgb первого div путем экспериментов. Складываем два значения вместе и затем применяем альфа-канал.

R: (128 + 255) * 0.5 = 191.5
G: (128 + 0)   * 0.5 = 64
B: (128 + 0)   * 0.5 = 64

Пытался использовать тот же метод для второго div, но теперь все становится сложнее.

R: (((128 + 255) * 0.5) + 86)  * 0.5 = 138.5
G: (((128 + 0)   * 0.5) + 185) * 0.5 = 124.5
B: (((128 + 0)   * 0.5) + 11)  * 0.5 = 37.5

Я могу округлить G и B, чтобы получить точный результат, но R отличается на 1,5. И если я увеличу количество цветных слоев, я не знаю, какие результаты я получу.

Есть ли способ лучше его рассчитать?


Обновление: как подсказал Кайидо, я попытался использовать холст. То же самое, используя прямоугольники: Fiddle. Используется getImageData для извлечения rgb второго прямоугольника. Возвращенное значение было [122, 105, 6, 223]. Не используется для использования 8-битных целых чисел в качестве альфа-значения, поэтому [122, 105, 6, 0.8754]. Несмотря на то, что я извлек некоторое значение rgb, это не сплошной цвет, и это определенно не то, что я измерил в Photoshop, который равен 140,125,38.

Также, когда я сделал снимок экрана холста и проверил цвет второго прямоугольника, он был 139, 124, 37, но цвет #second div равен 140,125,38. Они не совсем то же самое.

В любом случае, я искал способ преобразовать возвращаемое значение из getImageData, то есть 122, 105, 6, 0.8754, в 140,125,38. Я подумал, что если я скомпенсирую недостающую непрозрачность следующим примером, я получу желаемое значение

122 * (255/223) = 139.5 // 140
105 * (255/223) = 120   // 125
6   * (255/223) = 6.86  // 38

что я сделал для R, но тот же метод не работает для G и B. Я пришел к выводу, что холст на самом деле не поможет, если нет способа преобразовать прозрачный цвет в сплошной.


person akinuri    schedule 22.10.2015    source источник
comment
Думаю, я бы пошел с холстом, нарисовал прямоугольники тех же цветов, а затем получил бы окончательное значение с помощью getImageData. Но вам нужно будет проверить, где перекрываются элементы и т. Д. Возможно, вы также могли бы попробовать html2canvas lib.   -  person Kaiido    schedule 22.10.2015
comment
@Kaiido Я попробовал ваш метод и извлек некоторое значение цвета, но все еще есть некоторые проблемы. Смотрите мое обновление.   -  person akinuri    schedule 22.10.2015
comment
@akinurt, простой способ преобразовать прозрачный цвет в сплошной на холсте - это перед этим заполнить весь холст белым :-)   -  person Kaiido    schedule 23.10.2015
comment
@Kaiido Haha. Вместо этого я применил background-color: white. Белый прямоугольник сработал. Хотя есть одна маленькая проблема. imageData возвращает [139, 124, 37, 255] для второго прямоугольника, но последний цвет #second div равен 140,125,38. Вы хоть представляете, почему цвета холста и div не совпадают?   -  person akinuri    schedule 23.10.2015
comment
Конечно, потому что цветовой профиль другой. Кроме того, если под окончательным цветом вы имеете в виду тот, который вы получили от PS, вы должны знать, что вы обработали 3 раза цвет: 1-й в CSS, второй при съемке, третий при открытии в PS. Если я использую системный colorPicker непосредственно в CSS, затем в моментальном снимке и, наконец, в открытом файле в PS, у меня нет ни одного раза тех же значений, которые дает мне PS. Кроме того, я думаю, что делать то, что вы хотите, довольно неэффективно, поскольку я думаю, что разные устройства будут выполнять смешивание с разными алгоритмами.   -  person Kaiido    schedule 23.10.2015


Ответы (1)


Используя подход Кайидо, мне удалось получить конечный результат наложения цветов с помощью холста.

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// default background
context.beginPath();
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = "white";
context.fill();

// body
context.beginPath();
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = "rgba(0,0,0,.5)";
context.fill();

// first div
context.beginPath();
context.rect(10, 10, 200, 100);
context.fillStyle = "rgba(255,0,0,0.5)";
context.fill();

// second div
context.beginPath();
context.rect(20, 20, 50, 50);
context.fillStyle = "rgba(86, 185, 11, .5)";
context.fill();

var imageData = context.getImageData(25, 25, 1, 1).data;

console.log(imageData); // 139,124,37
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
canvas {
  display: block;
}
<canvas id="canvas"></canvas>

Хотя это дает мне то, что я хочу, я все же хотел бы этого математически.

person akinuri    schedule 25.10.2015