JSFiddle - React, Tailwind, and code Playground
blendColors
by tonytlwu
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<table>
<thead><tr>
<th>Result</th>
<th>Input</th>
<th>Output</th>
</tr></thead>
<tbody id="target">
</tbody>
</table>
CSS
.pass {
color: green;
}
.fail {
color: red;
}
td {
border: 1px solid #ccc;
}
JavaScript
function blendColors(colors) {
colors = Array.isArray(colors) ? colors : [];
var base = [0, 0, 0, 0];
var mix;
var added;
while (added = colors.shift()) {
if (typeof added[3] === 'undefined') {
added[3] = 1;
}
// check if both alpha channels exist.
if (typeof base[3] === 'number' && typeof added[3] === 'number') {
mix = [0, 0, 0, 0];
// alpha
mix[3] = 1 - (1 - added[3]) * (1 - base[3]);
// red
mix[0] = Math.round((added[0] * added[3] / mix[3]) + (base[0] * base[3] * (1 - added[3]) / mix[3]));
// green
mix[1] = Math.round((added[1] * added[3] / mix[3]) + (base[1] * base[3] * (1 - added[3]) / mix[3]));
// blue
mix[2] = Math.round((added[2] * added[3] / mix[3]) + (base[2] * base[3] * (1 - added[3]) / mix[3]));
} else if (added) {
mix = added;
} else {
mix = base;
}
base = mix;
}
return mix;
}
var scenarios = [
{
input: [
[0, 0, 0, 0],
[255, 255, 255, 0],
[255, 0, 0, .5],
[0, 255, 0, .5]
],
output: [85, 170, 0, 0.75]
},
{
input: [
[255, 255, 255, 1],
[0, 0, 0, 0],
[0, 0, 0, 0]
],
output: [255, 255, 255, 1]
}
];
var output = [];
for (var i = 0, l = scenarios.length; i < l; i++) {
output.push('<tr>');
output.push((_.isEqual(blendColors(_.cloneDeep(scenarios[i].input)), scenarios[i].output) ? '<td class="pass">Pass' : '<td class="fail">Fail') + '</td>');
output.push('<td><pre>' + JSON.stringify(scenarios[i].input) + '</pre></td>');
output.push('<td><pre>' + JSON.stringify(scenarios[i].output) + '</pre></td>');
output.push('</tr>');
}
document.querySelector('#target').innerHTML = output.join('');