Color Mixer

by Raul Bojalil

TypeScript

const mixColors = (color1: string, color2: string) => {

  const parseColor = (color: string) => {

    if (color.startsWith("#")) {
      const parsedHexCode = color.length === 9 
      	? /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color)
        : /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
      return [
        parseInt(parsedHexCode?.[1] || "0", 16), 
        parseInt(parsedHexCode?.[2] || "0", 16), 
        parseInt(parsedHexCode?.[3] || "0", 16),
        parseInt(parsedHexCode?.[4] || "FF", 16) / 255
      ];
    }
    const parsedRgba = color.substring(color.indexOf('(') +1, color.length -1).split(',');
    return [
      parseInt(parsedRgba?.[0] || "0"), 
      parseInt(parsedRgba?.[1] || "0"), 
      parseInt(parsedRgba?.[2] || "0"),
      parseFloat(parsedRgba?.[3] || "1")
    ];
  }
  
  const base = parseColor(color1);
  const added = parseColor(color2);
  
  console.log({ base, added });

  const mix = [0,0,0,0];
  mix[3] = 1 - (1 - added[3]) * (1 - base[3]);
  mix[0] = Math.round((added[0] * added[3] / mix[3]) + (base[0] * base[3] * (1 - added[3]) / mix[3]));
  mix[1] = Math.round((added[1] * added[3] / mix[3]) + (base[1] * base[3] * (1 - added[3]) / mix[3]));
  mix[2] = Math.round((added[2] * added[3] / mix[3]) + (base[2] * base[3] * (1 - added[3]) / mix[3]));
  
  return `rgba(${mix.join(',')})`;
}

console.log(mixColors("#181817", "rgba(255, 255, 255, 0.08)"));
console.log(mixColors("rgba(42,42,42,1)", "#EDF35414"));