Random Hex generator (only grey colors) - javascript

I found on stackoverflow this color generator :
Math.random()*0xFFFFFF<<0
It works fine. The only problem is that I'd like to generate random colors, but only of different shades of grey.
I have no idea how I could achieve something like this.

var value = Math.random() * 0xFF | 0;
var grayscale = (value << 16) | (value << 8) | value;
var color = '#' + grayscale.toString(16);
color will be a random grayscale hex color value, appropriate for using in eg element.style properties.
Note: there are several ways to coerce the random floating-point number to an integer. Bitwise OR (x | 0) will usually be the fastest, as far as I know; the floor function (Math.floor(x)) is approximately the same speed, but only truncates for positive numbers (you'd have to use Math.ceil(x) for negative numbers). Bitwise operators won't work as expected for numbers that require more than 32 bits to represent, but Math.random() * 0xFF will always be in the range [0,255).

If you want to use RGB, rgb grays can be created by supplying the same number in all three arguments i.e. rgb(255,255,255) (the number must be between 0 and 255).
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
var randomNumberString = String(getRandomInt(0,255));
var color = "rgb(" + randomNumberString + "," + randomNumberString + "," + randomNumberString + ")";

Related

Random RGB color generator with JavaScript

I am trying to get something like this:
rbg(random, random, random);
Now when I put in Math.floor(Math.random() * 255) + 1 into the area, it works but for some reason most of the numbers are stuck in 255 and rarely change.
My code is:
function colorGen() {
document.getElementById("color1").style.backgroundColor = 'rgb('+
Math.floor(Math.random() * 255) + 1 + ',' + Math.floor(Math.random() * 255) + 1
+',' + Math.floor(Math.random() * 255) + 1 +')';
}
When I put brackets () around - ( Math.floor(Math.random() * 255) + 1 ) -, it works much better.
Why is this so?
#Xufox has the right answer in the comment there. For clarity, you'll want to restructure your code a little (and let's also fix that bug where you'll never get zero for any channel due to the +1):
function colorGen() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
document.getElementById("color1").style.backgroundColor = "rgb(" + r + "," + g + "," + b + ")";
}
When you use +1 inside a string it will generate as string and not as mathematical expression when you use () it generate as mathematical expression.
My reccomand:
Use params to random colors
function colorGen() {
var color1=Math.floor(Math.random() * 255) + 1;
var color2=Math.floor(Math.random() * 255) + 1;
var color3=Math.floor(Math.random() * 255) + 1;
document.getElementById("color1").style.backgroundColor = 'rgb('+ color1
+ ',' + color2
+',' + color3 +')';
}
<button id="color1" onclick="colorGen()">click me to change color</button>
When you “add” 1, it gets concatenated as a string, since you’re starting with "rgb(" +, and the result of “string + number” will be another string. Wrapping numerical expressions in parentheses makes the + operator do addition instead of concatenation.
The reason you get 255 is because the numbers you generate end up looking like this:
11
21
31
41
…
2531
2541
2551
The backgroundColor setter caps 8-bit values (ranging from 0 to 255) at a maximum of 255 (and a minimum of 0). This means, setting element.style.backgroundColor = "rgb(10000, -10000, 128)" results in a backgroundColor of "rgb(255, 0, 128)"
So when Math.floor(Math.random() * 255) generates a number from 1 to 25, then the highest resulting number becomes 251, which is below 255. Any other value — i.e. from 26 to 255 — results in a value higher than 255, so it just becomes 255 automatically.
The parentheses make the arithmetic expression to be evaluated before the concatenation.

Calculate color values from green to red

I would like to calculate color value according to given number.
0 -> pure red
100 -> pure green
example: 75 -> color, which is 75% from red to green.
I need this for expiration counter, which shows appropriate colors as days count down.
You could indeed go for the solution provided by #KamilT. Disadvantage of this method (imo) is that the colors in the middle (around 50) will get brownish and not very nice compared to your full red and green.
I think it would be much nicer to follow the color spectrum, and passing over orange and yellow, in stead of that ugly brownish.
This can easily by achieved by working with HSL values rather then RGB values. If you set the Hue value based on your number between 0 and 100 to a value between 0°(red) and 120°(green), and keep your Saturation at 100% and your Lightness at 50%, you should get nice bright colors.
I found a way to convert between rgb and hsl here: HSL to RGB color conversion
And I wrote a simple function to calculate your rgb value using the conversion function from the answer above:
// convert a number to a color using hsl
function numberToColorHsl(i) {
// as the function expects a value between 0 and 1, and red = 0° and green = 120°
// we convert the input to the appropriate hue value
var hue = i * 1.2 / 360;
// we convert hsl to rgb (saturation 100%, lightness 50%)
var rgb = hslToRgb(hue, 1, .5);
// we format to css value and return
return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
}
And I set up a fiddle to demonstrate the diffrences between the HSL method and the RGB method: http://jsfiddle.net/rE6Rk/1/
update a more versatile version:
If you do not want to work with a range from red to green, you can slightly adapt the above method. The value that determines the actual color in a hsl representation is the hue, so that's the one we'll need to calculate.
If you define the range of your hue, by providing the 0 and 1 value as parameters, the calculation of the hue value becomes basic math. Have a look at the updated method:
function percentageToHsl(percentage, hue0, hue1) {
var hue = (percentage * (hue1 - hue0)) + hue0;
return 'hsl(' + hue + ', 100%, 50%)';
}
As you can see I changed the API a bit. The parameters are as follows:
percentage: a value between 0 and 1
hue0: the hue value of the color you want to get when the percentage is 0
hue1: the hue value of the color you want to get when the percentage is 1
Also, there is no longer a need to calculate the rgb value, modern browsers support hsl values as is.
So now you can use the method as follows:
// green(120) to red(0)
color = percentageToHsl(perc, 120, 0);
// blue(225) to pink(315)
color = percentageToHsl(perc, 225, 315);
// blue (225) to yellow(45 + 360)
color = percentageToHsl(perc, 225, 405);
So if you want to go clockwise you have to make hue0 < hue1. If you want to go counter clockwise you have to make hue0 > hue1. And since these are degrees, you can just add or subtract 360 to force the direction. You can even use this technique to wrap around the hue circle multiple times.
I've created a new fiddle to demonstrate: https://jsfiddle.net/r438s65s/
The answer by Pevara is great. I have adapted his jsfiddle to my needs, and maybe it is useful for others too: http://jsfiddle.net/rE6Rk/8/
It allows to have an uneven distribution of colors. In my case I wanted everything below 0.5 (50) to be red. And a 0.75 would be in the middle between red and green. So instead of working with hard borders 0 and 1, they can both be shifted.
The changes are in the numberToColorHsl() function only:
* the i is a floating point 0-1 instead of the int 0-100
* additional params min/max
/**
* Convert a number to a color using hsl, with range definition.
* Example: if min/max are 0/1, and i is 0.75, the color is closer to green.
* Example: if min/max are 0.5/1, and i is 0.75, the color is in the middle between red and green.
* #param i (floating point, range 0 to 1)
* param min (floating point, range 0 to 1, all i at and below this is red)
* param max (floating point, range 0 to 1, all i at and above this is green)
*/
function numberToColorHsl(i, min, max) {
var ratio = i;
if (min> 0 || max < 1) {
if (i < min) {
ratio = 0;
} else if (i > max) {
ratio = 1;
} else {
var range = max - min;
ratio = (i-min) / range;
}
}
// as the function expects a value between 0 and 1, and red = 0° and green = 120°
// we convert the input to the appropriate hue value
var hue = ratio * 1.2 / 3.60;
//if (minMaxFactor!=1) hue /= minMaxFactor;
//console.log(hue);
// we convert hsl to rgb (saturation 100%, lightness 50%)
var rgb = hslToRgb(hue, 1, .5);
// we format to css value and return
return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
}
The visuals explain it better than words.
This is just simple maths ;)
Red = 255 - (255 * (Number / 100))
Green = 255 * (Number / 100)
Blue = 0
That's all.

What the valid range of HSV color

I'm playing with HSV color. I have an array of hsv after convert from rgb color:
//hsv[0], hsv[1], hsv[2]
var hsv = rgbToHsv(rgb[0], rgb[1], rgb[2]);
I will add or subtract it
hsv[0] += ...
hsv[1] += ...
hsv[2] += ...
And I need to valid the value before convert it back to rgb. What is the valid range of hsv?
Here is the function I using to convert rgb to hsv
function rgbToHsv(r, g, b) {
var r = (r / 255),
g = (g / 255),
b = (b / 255);
var min = Math.min(Math.min(r, g), b),
max = Math.max(Math.max(r, g), b),
delta = max - min;
var value = max,
saturation,
hue;
// Hue
if (max == min) {
hue = 0;
} else if (max == r) {
hue = (60 * ((g-b) / (max-min))) % 360;
} else if (max == g) {
hue = 60 * ((b-r) / (max-min)) + 120;
} else if (max == b) {
hue = 60 * ((r-g) / (max-min)) + 240;
}
if (hue < 0) {
hue += 360;
}
// Saturation
if (max == 0) {
saturation = 0;
} else {
saturation = 1 - (min/max);
}
return [(hue), (saturation * 100), (value * 100)];
}
Roughly the same algorithm is used for this online converter. You can check the article after for the opposite conversion.
H is definitely between 0 and 360, but regarding S and V it is different. Like most values for color conversion or color blending mode calculation, a float between 0 and 1 is used. I would say it is better because beeing a float means you can have all the levels of precision you want.
Now it is not uncommon (like on this online converter and your current javascript) to multiply it by 100 to get a percentage. Often rounded as well. What is important to understand with this rounding is that obviously it increases the chances of you getting a different RGB color if you convert back and forth rgb > hsv > rgb. If this is important, then you're better with the floats.
Since you are asking what is "valid", I would say it only depends on how you want to use it or where these numbers will be used.

Explain Math.floor(Math.random())

I have seen many places using Math.floor() and Math.random()
like below
$('a.random-color').hover(function() { //mouseover
var col = 'rgb(' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ')';
$(this).animate({
'color': col,
'paddingLeft': '20px'
},1000);
},function() { //mouseout
$(this).animate({
'color': original,
'paddingLeft': '0'
},500);
});
});
Why used Math.floor() and Math.random()?
Math.random will give you a floating point number between 0 (inclusive) and 1 (exclusive).
Multiplying that by 256 will give you a number in the range 0 (inclusive) through 256 (exclusive), but still floating point.
Taking the floor of that number will give you an integer between 0 and 255 (both inclusive).
It's the integer from 0 to 255 that you need to construct RGB values like rgb(72,25,183).
It seems a random color is desired - one with each component random between 0 and 255.
Math.random() returns a random number on [0,1) (ie it may be exactly zero or up to but not including one).
Multiplying that random value by 256 gives a random number on the range [0,256) (ie it may be 255.99, but never 256). Almost there, but not quite.
Math.floor() rounds the number downwards to the nearest whole integer, making the result an integer on [0,255] as desired.
Math.floor will give a whole number and gets rid of the decimals.
Math.random returns a number between 0 and 1 and therefore will produce decimal numbers when multiplied with 256. Thats why you want to use floor to get rid of the decimals otherwise the rgb values won't work.
The Math.floor() is to drop the decimal portion of the Number. It is the opposite of Math.ceil().
You can also double the invert bitwise operator (~~) to achieve the same as Math.floor() (though of course the floor() method is much more readable to most).
~~(Math.random() * 256)
Math.random returns value between 0 and 1. You are multiplying it with 256 so it will return some float value between 0 and 256. math.floor will omit fraction value from it.
~~Number is only the Math.floor() for positive numbers. For negative numbers, it is the Math.ceil().
For positive numbers you can use:
Math.floor(x) == ~~(x)
Math.round(x) == ~~(x + 0.5)
Math.ceil(x) == ~~(x + 1)
For negative numbers you can use:
Math.ceil(x) == ~~(x)
Math.round(x) == ~~(x - 0.5)
Math.floor(x) == ~~(x - 1)

Map a range of values (e.g. [0,255]) to a range of colours (e.g. rainbow: [red,blue]) in JavaScript

I'm sure this must be a fairly straightforward, but it's a difficult question to word. I don't even know what to google for.
I'm not looking for any complicated solution. Basically, I'm drawing lines on a Canvas, and I want different colours depending on the length of the line. Usually I just scale, say, the red channel (#ff0000 * (length of line)/(maximum line length)), but this solution isn't ideal. I'm just looking for an equation that will give me a #rrggbb value for a certain position on a rainbow gradient, if that makes sense.
Thank you to whoever can help with this! It's very much appreciated.
Since you're using canvas then you can probably use the HSL color space (correct me if I'm wrong). It would make the code much simpler:
function rainbow(n) {
n = n * 240 / 255;
return 'hsl(' + n + ',100%,50%)';
}
If you're ok with having your range from 0 to 240 then you can even remove the first line of this function. See DEMO.
This article describes a method to make rainbow colors in JS. Basically it uses the Sine function to make rainbow colors. In short, the equation you need is something like this. See DEMO.
function RainBowColor(length, maxLength)
{
var i = (length * 255 / maxLength);
var r = Math.round(Math.sin(0.024 * i + 0) * 127 + 128);
var g = Math.round(Math.sin(0.024 * i + 2) * 127 + 128);
var b = Math.round(Math.sin(0.024 * i + 4) * 127 + 128);
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
I ended up using something similar to #rsp 's answer
var getColorAtScalar = function (n, maxLength) {
var n = n * 240 / (maxLength);
return 'hsl(' + n + ',100%,50%)';
}

Categories

Resources