I have a poll system and I want answers for this poll to be colored. For example: If it\'s 10% it would be red, if 40% it would be yellow and if 80% it would be green, so I
I know this is originally an old javascript question, but I got here searching for CSS only solution, so maybe it will help others equally: It's actually quite simple:
Use the percentage as a HSL color value!
Red to Green spans H from 0
to 128
.(so you can pump the percentage up by 1.2
if you want). Example:
background-color:hsl(perc,100%,50%);
Where perc is just the number, without the %
sign.
A simple scheme using HSL along with fiddle:
function getColor(value){
//value from 0 to 1
var hue=((1-value)*120).toString(10);
return ["hsl(",hue,",100%,50%)"].join("");
}
tweak saturation and luminosity as needed. and a fiddle.
function getColor(value) {
//value from 0 to 1
var hue = ((1 - value) * 120).toString(10);
return ["hsl(", hue, ",100%,50%)"].join("");
}
var len = 20;
for (var i = 0; i <= len; i++) {
var value = i / len;
var d = document.createElement('div');
d.textContent = "value=" + value;
d.style.backgroundColor = getColor(value);
document.body.appendChild(d);
}
function hexFromRGBPercent(r, g, b) {
var hex = [
Math.floor(r / 100 * 255).toString( 16 ),
Math.floor(g / 100 * 255).toString( 16 ),
Math.floor(b / 100 * 255).toString( 16 )
];
$.each( hex, function( nr, val ) {
if ( val.length === 1 ) {
hex[ nr ] = "0" + val;
}
});
return hex.join( "" ).toUpperCase();
}
Credit goes to andrew. He was faster.
I know this is kind of bump to topic but I found one more way of doing it.
To do this you can also create a dynamic canvas of 100x1 dimension and apply gradient to it and then from function you just need to get pixel color of the percent location.
Here is the code : This is global:
/* dynamic canvas */
// this should be done once in a page so out of function, makes function faster
var colorBook = $('<canvas />')[0];
colorBook.width = 101;
colorBook.height = 1;
var ctx = colorBook.getContext("2d");
var grd = ctx.createLinearGradient(0, 0, 101, 0);
grd.addColorStop(0, "rgb(255,0,0)"); //red
grd.addColorStop(0.5, "rgb(255,255,0)"); //yellow
grd.addColorStop(1, "rgb(0,255,0)"); //green
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 101, 1);
Then the function:
function getColor(value) {
return 'rgba(' + ctx.getImageData(Math.round(value), 0, 1, 1).data.join() + ')';
}
Demo : https://jsfiddle.net/asu09csj/
You can do this in a few lines of code (not including comments) without the need for any color maps.
function hsl_col_perc(percent, start, end) {
var a = percent / 100,
b = (end - start) * a,
c = b + start;
// Return a CSS HSL string
return 'hsl('+c+', 100%, 50%)';
}
//Change the start and end values to reflect the hue map
//Refernece : http://www.ncl.ucar.edu/Applications/Images/colormap_6_3_lg.png
/*
Quick ref:
0 – red
60 – yellow
120 – green
180 – turquoise
240 – blue
300 – pink
360 – red
*/
Example: https://jsfiddle.net/x363g1yc/634/
No need for color maps (Unless it is a non-linear color change, which was not asked)
Warning: This is not compatible with IE8 or below. (Thanks Bernhard Fürst)
// Just used as a shortcut for below, completely optional
const red = 0,
yellow = 60,
green = 120,
turquoise = 180,
blue = 240,
pink = 300;
function hsl_col_perc(percent, start, end) {
var a = percent / 100,
b = (end - start) * a,
c = b + start;
// Return a CSS HSL string
return 'hsl(' + c + ', 100%, 50%)';
}
// Simple little animation
var percent = 0,
progressDiv = document.getElementById('progress'),
textDiv = document.getElementById('progress-text'),
progressContainerDiv = document.getElementById('progress-container')
function step(timestamp) {
percent = (percent < 100) ? percent + 0.5 : 0;
// Play with me!
let colour = hsl_col_perc(percent, red, green); //Red -> Green
progressDiv.style.backgroundColor = colour;
progressContainerDiv.style.borderColor = colour;
progressDiv.style.width = percent + '%';
textDiv.innerHTML = Math.floor(percent);
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
#progress {
width: 0%;
white-space: nowrap;
text-wrap: none;
height: 50px;
}
#progress-container {
border: solid 2px black;
width: 200px;
}
<h1 id="progress-text"></h1>
<div id="progress-container">
<div id="progress"></div>
</div>
Mattisdada's code was really helpful for me while I was making a chart to display statistics of some quiz results. I modified it a bit to allow "clipping" of the percentage (not sure what the right term is) and also to work both ways along the colour wheel, e.g. both from green(120) to red(0) and vice versa.
function pickColourByScale(percent, clip, saturation, start, end)
{
var a = (percent <= clip) ? 0 : (((percent - clip) / (100 - clip))),
b = Math.abs(end - start) * a,
c = (end > start) ? (start + b) : (start - b);
return 'hsl(' + c + ','+ saturation +'%,50%)';
}
Basically, by setting a percentage value to clip the scaling at, everything below that value will be coloured as your start colour. It also recalculates the scaling according to 100% - clip.
Let's go through an example scenario where I enter the following values:
end: 120 (green)
I end up with yellow, which is halfway between red and green. If I hadn't done the recalculation in step 1, I'd have ended up with a more greenish colour, which could be misleading.