admin管理员组

文章数量:1435859

I am building a free real color mixer for 3 colors. To feel real I first convert hex or rgb to hsl and calculate with h, s, l values. I figured out to mix 2 colors:

function hslMixer2c(hsl10,hsl11,hsl12,hsl20,hsl21,hsl22,amount1,amount2) { // read hsl10 as hsl1[0], 1st value from hsl string
    var amountTot = amount1 + amount2;
    if (Math.abs(hsl10 - hsl20) > 0.5) { hsl10 += 1; } // > 179.5 is shorter part from wheel to 359
    var h = (amount1 / amountTot) * hsl10 + (amount2 / amountTot) * hsl20;  
    var s = (amount1 / amountTot) * hsl11 + (amount2 / amountTot) * hsl21; 
    var l = (amount1 / amountTot) * hsl12 + (amount2 / amountTot) * hsl22; 
    if (h > 1) { h -= 1; } 

    return [h, s, l];
}

So far, so good...

But I want to add a 3th color to mix. I tried several calculations but the results are different when changing the order of the used colors.

function hslMixer3c(hsl10,hsl11,hsl12,hsl20,hsl21,hsl22,hsl30,hsl31,hsl32,amount1,amount2,amount3) { // read hsl10 as hsl1[0], 1st value from hsl string
    var amountTot = amount1 + amount2 + amount3;
    if (Math.abs(hsl10 - hsl20) > 0.5) { hsl10 += 1; } // > 179.5 is andere kant naar 359 korter)
    var hsl90 = (amount1 / amountTot) * hsl10 + (amount2 / amountTot) * hsl20;  // hsl9x is sub mix
    var hsl91 = (amount1 / amountTot) * hsl11 + (amount2 / amountTot) * hsl21; 
    var hsl92 = (amount1 / amountTot) * hsl12 + (amount2 / amountTot) * hsl22; 
    if (hsl90 > 1) { hsl90 -= 1; } 
    if (Math.abs(hsl90 - hsl30) > 0.5) { hsl90 += 1; } // > 179.5 is andere kant naar 359 korter)
    var h = hsl90 + (amount3 / amountTot) * hsl30;  
    var s = hsl91 + (amount3 / amountTot) * hsl31; 
    var l = hsl92 + (amount3 / amountTot) * hsl32; 
    if (h > 1) { h -= 1; } 

    return [h, s, l];
}

Set color 1st at 90, 2nd at 180, 3rd at 300 the calculation is first for color 1 and 2 and additional 3 gives 190. But when I take 3 and 1 as first, the color goes to the upper side of the wheel and gives with addition color 3 a whole other result off course.

Can anyone help me pointing to the right direction, maybe with a sample?

I am building a free real color mixer for 3 colors. To feel real I first convert hex or rgb to hsl and calculate with h, s, l values. I figured out to mix 2 colors:

function hslMixer2c(hsl10,hsl11,hsl12,hsl20,hsl21,hsl22,amount1,amount2) { // read hsl10 as hsl1[0], 1st value from hsl string
    var amountTot = amount1 + amount2;
    if (Math.abs(hsl10 - hsl20) > 0.5) { hsl10 += 1; } // > 179.5 is shorter part from wheel to 359
    var h = (amount1 / amountTot) * hsl10 + (amount2 / amountTot) * hsl20;  
    var s = (amount1 / amountTot) * hsl11 + (amount2 / amountTot) * hsl21; 
    var l = (amount1 / amountTot) * hsl12 + (amount2 / amountTot) * hsl22; 
    if (h > 1) { h -= 1; } 

    return [h, s, l];
}

So far, so good...

But I want to add a 3th color to mix. I tried several calculations but the results are different when changing the order of the used colors.

function hslMixer3c(hsl10,hsl11,hsl12,hsl20,hsl21,hsl22,hsl30,hsl31,hsl32,amount1,amount2,amount3) { // read hsl10 as hsl1[0], 1st value from hsl string
    var amountTot = amount1 + amount2 + amount3;
    if (Math.abs(hsl10 - hsl20) > 0.5) { hsl10 += 1; } // > 179.5 is andere kant naar 359 korter)
    var hsl90 = (amount1 / amountTot) * hsl10 + (amount2 / amountTot) * hsl20;  // hsl9x is sub mix
    var hsl91 = (amount1 / amountTot) * hsl11 + (amount2 / amountTot) * hsl21; 
    var hsl92 = (amount1 / amountTot) * hsl12 + (amount2 / amountTot) * hsl22; 
    if (hsl90 > 1) { hsl90 -= 1; } 
    if (Math.abs(hsl90 - hsl30) > 0.5) { hsl90 += 1; } // > 179.5 is andere kant naar 359 korter)
    var h = hsl90 + (amount3 / amountTot) * hsl30;  
    var s = hsl91 + (amount3 / amountTot) * hsl31; 
    var l = hsl92 + (amount3 / amountTot) * hsl32; 
    if (h > 1) { h -= 1; } 

    return [h, s, l];
}

Set color 1st at 90, 2nd at 180, 3rd at 300 the calculation is first for color 1 and 2 and additional 3 gives 190. But when I take 3 and 1 as first, the color goes to the upper side of the wheel and gives with addition color 3 a whole other result off course.

Can anyone help me pointing to the right direction, maybe with a sample?

Share Improve this question edited Mar 5, 2016 at 16:05 Harry asked Mar 5, 2016 at 15:49 HarryHarry 7961 gold badge9 silver badges27 bronze badges 6
  • How did you add a third color? By running this code twice, or by writing separate code whith an additional amount3? – Jongware Commented Mar 5, 2016 at 15:58
  • I write a separate code with additional amount 3. I will edit my question by adding that code. Sorry, I forgot. – Harry Commented Mar 5, 2016 at 16:03
  • Equations can be found on Wikipedia/hsl – Arif Burhan Commented Mar 5, 2016 at 16:08
  • Your 3rd ponent code essentially es down to running the 2-ponent code twice. Do you get another result if you do the calculations only once - amount1 * hsl1 + amount2 *hsl2 + amount3*hsl3? – Jongware Commented Mar 5, 2016 at 17:14
  • @RadLexus but I have to check if the difference between 2 colors is more or less then 179,5 for the exact calculation at the right side of the color wheel. This can't be done with 3 colors at once. – Harry Commented Mar 5, 2016 at 22:05
 |  Show 1 more ment

1 Answer 1

Reset to default 6

One approach might be to convert each of the colors hue angles into a vector format:

  x = Math.cos(hue / 180 * Math.PI) * saturation
  y = Math.sin(hue / 180 * Math.PI) * saturation
  z = lightness

and then simply sum up these vectors (axis by axis) and divide by the number of colors.

If you would like some colors to contribute more towards the final color than others you could multiply each vector by a weight (where the sums of all weights = 1) prior to adding the vectors.

Finally convert back to hue and saturation:

        h = Math.atan2(y, x) * 180 / Math.PI
        s = Math.sqrt(x * x + y * y)
        l = z

本文标签: javascriptCalculation (algorithm) to mix 3 hsl colorsStack Overflow