2

Given a colorpicker that looks like so:

enter image description here

I am trying to calculate the HSL values given the x and y position of the cursor plus the hue from the slider on the right. My math skills are pretty weak, and although what I have is close, trying to grab a really light full-strength colour is troublesome, (it ends up being too gray). This is the current function I'm using:

getHSL = function(h, x, y) {
  var hsl, hue, lightness, saturation;
  hue = parseInt(h, 10);
  if (hue === 360) {
    hue = 0;
  }
  saturation = x;
  lightness = (50 * (1 - (x / 100)) + 50) * (1 - (y / 100));
  hue = Math.round(clamp(hue, 0, 360));
  saturation = Math.round(clamp(saturation, 0, 100));
  lightness = Math.round(clamp(lightness, 0, 100));
  hsl = {
    hue: hue,
    saturation: saturation,
    lightness: lightness
  };
  return hsl;
};

Is this the wrong way to do it? The results are actually very close to correct, but a tad off with really light full-strength colors.

Collin Henderson
  • 1,154
  • 10
  • 22
  • I would suggest clamping x,y to 0-1 before you begin, it makes everything cleaner. (ie lightness would be `((1-x) * .5 + .5) * (1-y)`) I also use THREE.Color, which clamps everything to 0-1 (hsl, rgb) It has helpers for .getStyle(), .getHSL, setHSL, etc – dansch Apr 02 '18 at 01:43

1 Answers1

1

It looks like your colour picker is expressed in the HSV (Hue/Saturation/Value) coordinates.

Wikipedia has a decent article on this and you can work out the conversion formula from the information given there.

Alternatively a quick search on Google returns, e.g., this page with a formula that you can use to convert HSV to HSL: http://codeitdown.com/hsl-hsb-hsv-color/. Assuming that your x and y both run from 0 to 100, the calculation should read:

hsv_value = 1 - (y / 100);
hsv_saturation = x / 100;
lightness = (hsv_value / 2) * (2 - hsv_saturation);
saturation = (hsv_value * hsv_saturation) / (1 - Math.abs(2 * lightness - 1));

This returns saturation and lightness in the range [0,1]. Also, why are you clamping your x and y coordinates?

Saran Tunyasuvunakool
  • 1,064
  • 1
  • 9
  • 23
  • Yes! This indeed works perfectly. Thank you very much :) – Collin Henderson May 07 '14 at 15:13
  • As an aside, I also needed to check to make sure saturation didn't end up as a NaN which can happen if the expression ends up trying to divide by zero on `#fff` and `#000`. In that case, just using the original `hsv_saturation` does the trick. – Collin Henderson May 07 '14 at 16:15