I'm creating a "characters remaining" type counter for a site of mine, and am trying to get smooth color transitions.
How would I go about creating a function to obtain the hex value for a color if I pass the maximum number (in this case 300) and the current char count assuming the pattern is green, yellow, orange, red?
This is in Javascript. Here is what I have so far:
function commentcounter(val) {
max = 300;
if(val >= max){
color = '#FF0000';
}else if(val > (max / 2)){
color = '#FF9900';
}else{
color = '#00FF00';
}
display = '<span style="color:' + color + '">' + val + '/' + max + '</span>';
document.getElementById('counter').innerHTML = display;
}
As you can see, this doesn't really interpolate, just goes from green to orange to red.
You need to interpolate each color component individually from 0 to 255 (or vice-versa).
This will be much easier if you use color: rgb(0, 255, 0).
"rgb("+Math.round(Math.min((((chars+(max/2))*2/max)-1)*255,255))+","+Math.round(Math.min(((chars*-2/max)+2)*255,255))+",0)";
This worked better than rgb() for me:
var pct = val / max;
var h = pct * 120;
var newColor = 'hsl(' + h + ', 80%, 50%)';
http://jsfiddle.net/ehUHp/
Related
So I'm working on my WordPress site and what I ran into with this background color code is that it produces the same color for every article that has the same amount of characters:
function setBgColor() {
var titleLength = document.getElementsByClassName('fl-heading-text')[0].innerText.length;
var hue = titleLength * 100 % 360;
var bgColor = "hsl( " + hue + ", 90%, 60% )";
document.getElementsByClassName("fl-page-content")[0].style.background = bgColor;
}
setBgColor();
What I am attempting to do now is add a bit of variation so that even if two or more articles have the same title length, the saturation output won't necessarily be the same.
I've attempted to modify it in the following way, but when I'm using Math.random I'm no longer receiving a background with color, but a white background like the code isn't working:
function setBgColor() {
var titleLength = document.getElementsByClassName('fl-heading-text')[0].innerText.length;
var hue = titleLength * 100 % 360;
var x = Math.floor((Math.random() * 100) + 1);
var bgColor = "hsl( " + hue + ", " + x + ", 60% )";
document.getElementsByClassName("fl-page-content")[0].style.background = bgColor;
}
setBgColor();
Thank you for helping me wrap my head around this.
With hsl values, the first number is a number between 0-255, and the other two numbers are percents. You need to add a percent sign after your random saturation.
"hsl( " + hue + ", " + x + "%, 60% )";
I want to change color of the dot every time it hits the wall. I saw few solutions, but I don't know why mine isn't working.
Here's the part responsible for changing color:
function chColor() {
hex = Math.floor(Math.random() * 100000 + 1);
color = '"' + "#" + hex + '"';
color.toString();
return color;
}
And here is not working fiddle:
https://jsfiddle.net/vpzd7ye6/
Colour overkill
This answer is way overkill and I was about to discard it, but, why not give a Better random colour for those who may need it... (|:D
When random seams less random
Selecting a random totally random colour for us humans does not work that well if you wish to have a clear distinct change that attracts the eye from one colour to the next.
The problem is that many of the colour values available are very close to white or black and a totally random colour may be very close to the last making the change impossible to notice.
Simple random colour
So first the simple random colour picks a totally random colour from all of the 16,777,216 possible colours.
function randColor(){
return "#" +
(Math.floor(Math.random() * 0x1000000) + 0x1000000)
.toString(16)
.substr(1);
}
The function works by finding a random 24 bit number (0 - 0xFFFFFF same as 0 - 16777216). Because numbers do not have leading zeros added all random values below 0x100000 will, when converted to hex have less than 6 digit (the CSS colour value requires 3 or 6 digit Hex value) so I add 0x1000000 to ensure that the number is > 0x100000 and will always have 7 digits. As the first (left most) digit is not needed I use substr to remove it. Then added the "#" and return.
The function Number.toString(radix) takes an argument called radix which specifies the base the number is converted to. It defaults if not supplied to 10 (base ten is what we humans use). The hex colour is base 16 so that must be specified. The toString radix argument can be any value from 2 (binary) to 36 (which uses characters 0-9 then A-Z)
Less is more Random
Ironically we humans tend to find less random sequences more random than true random sequences. Many music players use this type of random sequence when they have the play set to shuffle, to ensure tracks are not played twice in a row or that repeated sequences of tracks are played by random chance.
To make the random colour seem more random and distinct you should track the last colour return so that you can ensure you are not close to that colour. You should also use a random colour that stays away from the whites and blacks.
var randColour = (function(){ // as singleton so closure can track last colour
var lastHue = 0;
const minChange = 360 / 3; // Hue distance from last random colour
var lastVal = false; // for low high saturation and luminance
const randomAmount = 360 / 3; // random hue range
const minVal = 20; // how far from full black white to stay (percent)
const minSat = 80; // how far from grey to stay (percent)
return function(){
var hueChange = Math.random() * randomAmount ;
hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
lastHue += 360 + hueChange + minChange; // move away from last colour
lastHue %= 360; // ensure colour is in valid range
var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
// switch between high and low and luminance
lastVal = ! lastVal;
if(lastVal){
val = minVal + val;
} else {
val = 100 - minVal - val;
}
return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
}
})(); // call singleton
This function returns a random colour but ensures that the saturation and value stay within a specific range and that the hue is at least 1/3 around the colour wheel from the last value. It cycles between low and low and high luminance values to make the colour change as clear as possible. Closure is used to keep track of the last colour returned. The function returns the random colour as a CSS hsl(hue, saturation, luminance) color string.
There are two constants that control the colour sequence. minVal set to 20 is the percentage to stay away from full black or full white. Valid range is 0-~50 and minSat set to 80 is how far to stay away from grays in percent.
const minSat = 80; // how far from grey to stay (percent)
Compare change
To compare the two methods the following demo shows side by side a set of random colours using both methods, then flashes a new random colour 4 times a second. The simple random colour will appear from time to time to miss a change. I leave it up to you to pick which side is which.
var canvas = document.createElement("canvas");
canvas.width = 620;
canvas.height = 200;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var randColour = (function(){ // as singleton so closure can track last colour
var lastHue = 0;
const minChange = 360 / 3; // min hue change
var lastVal = false; // for low high saturation and luminance
const randomAmount = 360 / 3; // amount of randomness
const minVal = 20; // how far from full black white to stay (percent)
const minSat = 80; // how far from grey to stay (percent)
return function(){
var hueChange = Math.random() * randomAmount ;
hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
lastHue += 360 + hueChange + minChange; // move away from last colour
lastHue %= 360; // ensure colour is in valid range
var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
// switch between high and low and luminance
lastVal = ! lastVal;
if(lastVal){
val = minVal + val;
} else {
val = 100 - minVal - val;
}
return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
}
})(); // call singleton
function randColor(){
return "#" +
(Math.floor(Math.random() * 0x1000000) + 0x1000000)
.toString(16)
.substr(1);
}
const grid = 16;
var gridX = 0;
var gridY = 0;
var bigSize = grid - (grid / 3 ) * 2;
const xStep = Math.floor((canvas.width - 12) / (grid * 2));
const yStep = Math.floor(canvas.height / grid);
var count = 0;
function drawRandomColour(){
ctx.fillStyle = randColor(); // simple random colour
ctx.fillRect(gridX * xStep, gridY * yStep, xStep, yStep);
ctx.fillStyle = randColour(); // smart random colour
ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep, yStep);
if(count < grid * grid - 1){ // fill the grid
gridX += 1; // move to next grid
if(gridX > grid-1){
gridX = 0;
gridY += 1;
gridY %= grid;
}
count += 1;
setTimeout(drawRandomColour,1); // quickly fill grid
return; // done for now
}
// if grid is full pick a random grid loc and request the next random colour
gridY = gridX = (grid / 3);
setTimeout(centerChange,250); // every quarter second
}
function centerChange(){
ctx.fillStyle = randColor(); // simple random colour
ctx.fillRect(gridX * xStep, gridY * yStep, xStep * bigSize, yStep * bigSize);
ctx.fillStyle = randColour(); // smart random colour
ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep * bigSize, yStep * bigSize);
setTimeout(centerChange,250); // every quarter second
}
drawRandomColour(); // start it up.
Compare sequences
This demo just draws the random colours as a sequence of random values. Examine the sequences to see how often you see two or more colours in a row that are hard to distinguish between. You will find that the sequence on the left has more similar sequences than the one on the right.
Expand demo to full-page view to see both sequences.
Click to redraw sequences.
var canvas = document.createElement("canvas");
canvas.width = 1240;
canvas.height = 800;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var randColour = (function(){ // as singleton so closure can track last colour
var lastHue = 0;
const minChange = 360 / 3; // min hue change
var lastVal = false; // for low high saturation and luminance
const randomAmount = 360 / 3; // amount of randomness
const minVal = 20; // how far from full black white to stay (percent)
const minSat = 80; // how far from grey to stay (percent)
return function(){
var hueChange = Math.random() * randomAmount ;
hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
lastHue += 360 + hueChange + minChange; // move away from last colour
lastHue %= 360; // ensure colour is in valid range
var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
// switch between high and low and luminance
lastVal = ! lastVal;
if(lastVal){
val = minVal + val;
} else {
val = 100 - minVal - val;
}
return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
}
})(); // call singleton
function randColor(){
return "#" +
(Math.floor(Math.random() * 0x1000000) + 0x1000000)
.toString(16)
.substr(1);
}
const grid = 32;
var gridX = 0;
var gridY = 0;
const xStep = Math.floor((canvas.width - 12) / (grid * 2));
const yStep = Math.floor(canvas.height / grid);
var count = 0;
function drawRandomColour(){
ctx.fillStyle = randColor(); // simple random colour
ctx.fillRect(gridX * xStep, gridY * yStep, xStep, yStep);
ctx.fillStyle = randColour(); // smart random colour
ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep, yStep);
if(count < grid * grid - 1){ // fill the grid
gridX += 1; // move to next grid
if(gridX > grid-1){
gridX = 0;
gridY += 1;
gridY %= grid;
}
count += 1;
setTimeout(drawRandomColour,1); // quickly fill grid
return; // done for now
}
}
drawRandomColour(); // start it up.
// redraw on click
canvas.addEventListener("click",function(){
if(count >= grid * grid - 1){
gridX = gridY = count = 0;
drawRandomColour();
}else {
gridX = gridY = count = 0;
}
});
Summary
Though the second random function is not perfect, It can from time to time get colours that within a context appear similar this occurs much less than by pure random. When it is important for the user to notice a visual changes the best approch is to cycle two complementary colours (hue + 180) with one having a high luminance and the other a low. The CSS hsl colour string makes it easy to pick luminance and hue and when you want random colours gives you better control.
The problem is in converting number to hex color string.
So you can write a function that converts random number to valid hex color (see what this function does):
function convertToColor(num){
return '#' + ('00000' + (num | 0).toString(16)).substr(-6);
}
and then just use it in chColor function:
function chColor() {
number = Math.floor(Math.random() * 100000 + 1);
color = convertToColor(number);
return color;
}
Here is the link with working example: jsfiddle
Also it makes sense to rename function to getRandomColor:
function getRandomColor(){
number = Math.floor(Math.random() * 100000 + 1);
return convertToColor(number);
}
Please check updated fiddle
I just changed your chColor function on this:
function chColor() {
color = "#" + ((1 << 24) * Math.random() | 0).toString(16);
return color;
}
I have updated the fiddle. Link https://jsfiddle.net/vpzd7ye6/2/
I made the following change to your change color function;
function chColor() {
hex = Math.floor(Math.random() * 1000000) + 1;
color = '' + '#' + hex + '';
return color;
}
I want to change text color as per background between lighter to darker color.
What I wanted to do as below:
[background Color] + -------- - Text with Background
So here if I choose background Green then "Text with background" text color can switch from lighter color to darker color using + -
I've used below code.
Code
<input type="range" name="bgopacity" id="bgopacity" value="0" min="0" max="765" step="1" onchange="rangevalue.value=value">
<span class="txtcolor">Text With Background</span>
<script>
var rval = bval = gval = 0;
$('#bgopacity').on('change keyup mouseout keypress click mouseenter mouseup', function (value) {
var valcnt = $(this).val();
if (valcnt <= 255) {
rval = valcnt;
gval = bval = 0;
} else if (valcnt >= 255 && valcnt <= 510) {
rval = 255;
gval = valcnt - rval;
bval = 0;
} else if (valcnt >= 510) {
rval = gval = 255;
bval = valcnt - (gval + rval);
}
$('.txtcolor').css('color','rgb('+Math.round(rval)+','+Math.round(gval)+','+Math.round(bval)+')');
});
</script>
This code is working perfectly, but only some colors are changing. So I need more color switch between 0 to 765.
Can you please help me to find out relative code? Thanks in advance.
If I understood correctly, you want to have the user pick a color and, after that, have a slider that allows the user to lighten or darken the color selected.
Instead of the RGB model (0 - 255 for Red, Green and Blue, respectively), I'd recommend you check out the HSL model.
HSL stands for Hue , Saturation and Luminosity. This CodePen project demonstrates very well how HSL and RGB differ.
The Hue is an angle from 0° - 360° (the deg suffix in CSS is optional)
It defines what color you're working with. Red is at 0°, green is at 120° and blue is at 240°, looping back to red at 360°. You can pick any of the beautiful nuances of color in between 0° and 360°.
The Saturation is a percentage from 0% to 100% (with the % suffix in CSS)
It defines how colorful the color is. 100% saturation means the color is at its full potential. 0% saturation is just a sad, gray mess.
The Luminosity is a percentage from 0% to 100% (with the % suffix in CSS)
It defines how bright the color is, how close it is to being black or white.
The hsl() usage in CSS is very similar to the rgb()'s:
element {
color: hsl(190, 90%, 55%); /* this is a beautiful cyan color */
}
Basically, where in RGB you have to pick the amount of each color to add up, in HSL you can pick what color and what to do with it.
So, in your case, the user would first choose the H (hue) part, which defines what color it is.
Then you could have a slider for L (luminosity), and let the user define just how bright the background color is.
Here's a working example of your task, but with HSL (I've added saturation as well but it can be easily removed if unnecessary):
var hue_picker = document.getElementById("hue-picker");
var sat_picker = document.getElementById("sat-picker");
var lum_picker = document.getElementById("lum-picker");
var txt = document.getElementById("txt");
var div = document.getElementById("div");
function filter_input(input, min, max) {
return Math.max(min, Math.min(input, max))
}
function update_color() {
// Filter out inputs that are greater than max or lesser than min
var hue = filter_input(hue_picker.value, 0, 360);
var sat = filter_input(sat_picker.value, 0, 100);
var lum = filter_input(lum_picker.value, 0, 100);
// (background has a fixed 50% luminosity)
div.style.backgroundColor = "hsl(" + hue + ", " + sat + "%, 50%)";
txt.style.color = "hsl(" + hue + ", " + sat + "%, " + lum + "%)";
// Update the text to display current HSL values
txt.innerText = "background-color: hsl(" + hue + ", " + sat + "%, 50%);\n"
+ "color: hsl(" + hue + ", " + sat + "%, " + lum + "%);";
}
hue_picker.onchange = hue_picker.oninput = update_color;
sat_picker.onchange = sat_picker.oninput = update_color;
lum_picker.onchange = lum_picker.oninput = update_color;
#div {
height: 100px;
width: 300px;
}
#txt {
font-family: monospace;
}
<input type="range" id="hue-picker" value="0" min="0" max="360" step="1"/>
<input type="range" id="sat-picker" value="100" min="0" max="100" step="1"/>
<input type="range" id="lum-picker" value="75" min="0" max="100" step="1"/>
<div id="div">
<span id="txt">Text With Background</span>
</div>
Hopefully this is still relevant / useful to you! Cheers!
This question already has answers here:
Random color generator
(64 answers)
Closed 8 years ago.
I have this code that uses RGB color selection and I was wondering how to make JavaScript do a random color using the RGB method and remember it throughout the code.
EDIT: I tried this:
var RGBColor1 = (Math.round, Math.random, 255)
var RGBColor2 = (Math.round, Math.random, 255)
var RGBColor3 = (Math.round, Math.random, 255)
but it doesn't work. Help please!
EDIT 2: The code uses this:
g.fillStyle="rgba(R,G,B,0.2)";
g.strokeStyle="rgba(R,G,B,0.3)";
E();
The letters represent the color of RGB.
EDIT 3: The doubles of this question are using HEX values, not RGB values.
function random_rgba() {
var o = Math.round, r = Math.random, s = 255;
return 'rgba(' + o(r()*s) + ',' + o(r()*s) + ',' + o(r()*s) + ',' + r().toFixed(1) + ')';
}
var color = random_rgba();
g.fillStyle = color;
g.strokeStyle = color;
FIDDLE
const randomBetween = (min, max) => min + Math.floor(Math.random() * (max - min + 1));
const r = randomBetween(0, 255);
const g = randomBetween(0, 255);
const b = randomBetween(0, 255);
const rgb = `rgb(${r},${g},${b})`; // Collect all to a css color string
Here's a very simple method that works off of a single random number generation. Basically, it generates a number between 0 and 0xfffff (or 2^24, the highest number you can get from 24 bits). The highest value you can get from 8 bits is 255. This algorithm takes the left-most 8 bits of the random number for RED, the middle 8 bits for GREEN, and the last 8 bits for BLUE, using all 24 bits of the random number.
function getRandomRgb() {
var num = Math.round(0xffffff * Math.random());
var r = num >> 16;
var g = num >> 8 & 255;
var b = num & 255;
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
for (var i = 0; i < 10; i++) {
console.log(getRandomRgb());
}
Console output (sample):
rgb(2, 71, 181)
rgb(193, 253, 111)
rgb(172, 127, 203)
rgb(203, 53, 175)
rgb(226, 45, 44)
rgb(102, 181, 19)
rgb(92, 165, 221)
rgb(250, 40, 162)
rgb(250, 252, 120)
rgb(67, 59, 246)
Adapted from source.
I'm using a HTML table heatmap JQuery script by:
http://www.designchemical.com/blog/index.php/jquery/jquery-tutorial-create-a-flexible-data-heat-map/
I've been able to modify it and get it cleaned up and working with our data sets. However, the current script only allows for two colors and does not calculate the medium with a standard deviation to include a third color such as yellow.
Here is the current script below:
<script type="text/JavaScript">
$(document).ready(function () {
// Function to get the Max value in Array
Array.max = function (array) {
return Math.max.apply(Math, array);
};
// get all values
var counts = $('.heatmap tbody td').not('.first_row').map(function () {
return parseInt($(this).text().replace(/,/g, "").replace(/\(|\)/g, ""));
}).get();
// return max value
var max = Array.max(counts);
// red color for lowest data
xr = 251;
xg = 121;
xb = 105;
// green color for highest data
yr = 138;
yg = 251;
yb = 107;
n = 100;
// add classes to cells based on nearest 10 value
$('.heatmap tbody td').not('.first_row').each(function () {
var val = parseInt($(this).text().replace(/,/g, "").replace(/\(|\)/g, ""));
var pos = parseInt((Math.round((val / max) * 100)).toFixed(0));
red = parseInt((xr + ((pos * (yr - xr)) / (n - 1))).toFixed(0));
green = parseInt((xg + ((pos * (yg - xg)) / (n - 1))).toFixed(0));
blue = parseInt((xb + ((pos * (yb - xb)) / (n - 1))).toFixed(0));
clr = 'rgb(' + red + ',' + green + ',' + blue + ')';
$(this).css({
backgroundColor: clr
});
});
});
</script>
The heatmap currently goes from red to green and I want to add a calculation that adds yellow for the medium range. I've created a jsFiddle here: http://jsfiddle.net/7z8D4/ with the script and heatmap table structure I'm using.
For Example, if I have the following data sets, it should be colored such as:
1 red
2 red
3 pink
4 pink
5 yellow
6 yellow
7 lime green
8 lime green
9 green
10 green
I really appreciate any insights on this. :)
red (at 0%) to yellow (at 50%) to green (at 100%)
var pos = val / (max * 1.0);
red = Math.round(pos < 0.5 ? 255 : ((1 - pos) * 2) * 255);
green = Math.round(pos < 0.5 ? (pos * 2) * 255 : 255);
blue = 0;
I've created a pretty simple JavaScript function (see http://jsfiddle.net/4vCfc/) that provides an RGB color on a Red through yellow and then blue color gradient that I'm using for a heatmap to demonstrate usage of fields in a form.
Here's the function definition:
function getHeatColorAsRbg(percentage) //percent is a number between 0 and 1.
{
//RED - YELLOW (255, 0, 0) to (255, 255, 0)
//THEN YELLOW TO BLUE (255,255,0) to (0, 0, 255)
var red = 0;
var blue = 0;
var green = 0;
//Two cases - 1.0 down to 0.5 and 0.5 down to 0.
if(percentage >= 0.5)
{
red = 255;
green = Math.round(255 * 2 * (1 - percentage));
blue = 0;
}
else
{
blue = 255 - Math.round((percentage/0.5)*255);
red = 255 - blue;
green = red;
}
return "rgb(" + red + "," + green + "," + blue + ")";
}
Without finding the Minimum in array your methods are just half-methods.))