React

Hi there. I have a question from Random Color Picker project in react. I dont get the part with isLight method especially “< 127 * 3” one.

Random Color Picker

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { Button } from ‘./Button’;
class Random extends React.Component {
constructor(props){
super(props);
this.state = {color: [5 , 200, 100]};
this.handleClick = this.handleClick.bind(this)
}
componentDidMount() {
this.applyColor();
}

componentDidUpdate(prevProps, prevState) {
this.applyColor();
}

formatColor(ary) {
return ‘rgb(’ + ary.join(', ') + ‘)’;
}

 isLight() {
    const rgb = this.state.color;
    return rgb.reduce((a,b) => a+b) < 127 * 3;
  }

applyColor() {
const color = this.formatColor(this.state.color);
document.body.style.background = color;
}

chooseColor() {
const random = ;
for (let i = 0; i < 3; i++) {
random.push(Math.floor(Math.random()*256));
}
return random;
}
handleClick() {
this.setState({color: this.chooseColor()})
}

render() {
return (


<h1 className={this.isLight() ? ‘white’ : ‘black’}>
Your color is {this.formatColor(this.state.color)}



);
}
}

ReactDOM.render(
,
document.getElementById(‘app’)
);

Hi there, and welcome to the forums!

The important thing to note is that when the colour of the background changes, the text displaying the current colour will become more or less visible based on which background colour gets chosen. What if you have white text and the background picked is yellow? Then the text would be barely visible and that’s not what we want! Therefore we want to be able to change the text colour to contrast with whatever background colour has been chosen.

Now thinking about RGB colour codes, we can note something. If you have full saturation on all colours i.e. rgb(255, 255, 255) then the colour you get is white. Likewise, if you have no saturation on all colours i.e. rgb(0, 0, 0) then you get black. Note that the exact middle of white and black would be rgb(127, 127, 127), that’ll be important. Anything in between has the colour picked based on the combo, but the important factor is that the lightness of the colour is related to the size of the numbers. If you have something like rgb(200, 150, 170) This colour is clearly 3 very high values and thus is close in value to pure white, and the same works for 3 low values being close to black.

Thus what we can extrapolate from all this is that if you average the 3 values and it’s high, then the colour is a light colour, and if the average is low then it’s a darker colour. We essentially compare that against the exact middle of white and black to determine if a given colour is closer to white than black, and since the max value for each is 255, we can take 255/2 = 127.5 as the median value (where in this case they’ve rounded down, but rounding up would be fine also. Thus we get our final formula where we have, for a given background colour rgb(a, b, c):

  1. [If a + b + c > 127 + 127 + 127] (i.e. 127 * 3) then rgb(a, b, c) must be closer to white than the middle colour, thus we can call this a light colour.
  2. [If a + b + c < 127 * 3 then rgb(a, b, c) must be closer to black than the middle colour, thus we can call this a dark colour.

And that’s exactly what your code does:

rgb.reduce((a,b) => a+b) < 127*3
# The left part just sums the numbers in the rgb colour,
# and the right part is the sum of the exact middle colour

Hopefully this makes sense now as it can be quite confusing the first time you see it!

2 Likes

Hey thank you for replaying. Your explanation was very good and clear. I really appreciate that!

1 Like