最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Calculation (algorithm) to mix 3 hsl colors - Stack Overflow

programmeradmin3浏览0评论

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
发布评论

评论列表(0)

  1. 暂无评论