javascriptreactjscolorsjsxcolor-picker

How do I calculate the color RGB code in a color picker?


I'm trying to make a reusable color color picker component in react, I want to calculate the RGB color code using the mouse coordinates on a 256 by 256 div, the div has a white background color and it has two css gradients, in it the first one is black from the bottom and transparent to the top, the second is blue to the right and transparent to the left, I'm currently assuming that blue is being picked I want to make it dynamic later, in my calculateColor function I assume that the blue channel is y - 255 please correct me if i'm wrong, but I don't know how to calculate the red and green channel.

function calculateColor(x: number, y: number) {
  const r = // ???
  const g = // ???
  const b = 255 - y
          
  return `rgb(${r}, ${g}, ${b})`;
}

JSX

<div className="colors" onMouseDown={e => colorsMouseDown(e, "colors")} ref={colorsRef}>
  <div className="gradient1"></div>
  <div className="gradient2"></div>
  <div className="picker" draggable="false" ref={colorsPickerRef} />
</div>

I tried to calculate red and green channel using Math.max but it doesn't seem to be right because I took a screenshot of it and I picked the picked color in and it doesn't match the calculated color in the red and green channel, but it does match the blue channel.

function calculateColor(x: number, y: number) {
  const r = 255 - Math.max(x, y);
  const g = 255 - Math.max(x, y);
  const b = 255 - y
          
  return \`rgb(${r}, ${g}, ${b})\`;
}

CSS

.ColorPicker .colors {
  grid-area: 1 / 1 / 2 / 2;
  overflow: hidden;
  position: relative;
  background-color: #fff;
}
.ColorPicker .colors .gradient1,
.ColorPicker .colors .gradient2 {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
.ColorPicker .colors .gradient1 {
  background: linear-gradient(to left, #00f, transparent);
}
.ColorPicker .colors .gradient2 {
  background: linear-gradient(0deg, #000, transparent);
}

if you put this picture in another color picker and pick the color in the circle it would be rgb(32, 32, 99) which is different than the color shown


Solution

  • You have two overlapping divs. The lower div is blue and the upper div is black. Both divs have a gradient for transparency. At the bottom, the black div has no transparency. At the right, the blue div has no transparency.

    First, I calculate the blue background div

    255 - x
    

    and then the black div:

    function calculateColor(x, y) {
      const r = g = Math.round((255 - x) * (255 - y) / 255);
      const b = 255 - y;
              
      return `rgb(${r}, ${g}, ${b})`;
    }
    
    console.log(calculateColor(174, 157));