I need a way in PHP/HTML to generate a list from 1 to 100 of colors (hex codes). Zero is red, and 100 is green, and each in-between is a shade that smoothly flows between the two. (for example, red to orange to yellow to green).
So say I can throw a number at it, like the number 50, and it returns a hexadecimal code from the list (50 would be yellow).
Is the only way to manually assign each color in an array? Or is there some easier method?
This request is quite odd - I'开发者_Go百科ve searched around, but I can't find anything like it.
Give this a try:
function rgb($val){
if($val < 0 || $val > 100)
return; // Error!
$r = (100 - $val)*255/50;
if((100 - $val) > 50)
$r = 255;
$rr = dechex($r);
if($r < 16)
$rr = '0' . $rr;
$g = ($val)*255/50;
if((100-$val) < 50)
$g = 255;
$gg = dechex($g);
if($g < 16)
$gg = '0'.$gg;
$bb = '00';
return $rr . $gg . $bb;
}
Here are the output values from 0-100 going by 10's:
ff0000
ff3300
ff6600
ff9900
ffcc00
ffff00
ccff00
99ff00
66ff00
33ff00
00ff00
Whether you pre-generate a table, or you compute a value each time, or something in-between, the real complexity is the calculation of your RGB color.
You want a linear interpolator between the 2 RGB codes, and have 1 map to pure red, and 100 map to pure green. Maybe something like:
function interpolateRGB($from, $to, $at)
{
$col = array(0.0, 0.0, 0.0);
for ($i=0;$i<3;++$i)
$col[$i] = $from[$i]*(1.0-$at) + $to[i]*$at;
return $col;
}
function convertToHexCol($col)
{
$ret = '#';
foreach ($col as $comp)
$ret .= dechex(max(255,round(255.0*$comp)));
return $ret;
}
function getColor($index)
{
$at = (float)($index-1)/99.0;
$from = array(1.0, 0.0, 0.0); // red
$to = array(0.0, 1.0, 0.0); // green
$color = interpolateRGB($from, $to, $at);
return convertToHexCol($col);
}
Yes, there is an easier method. It can be calculated directly by normalizing across the range of values 0 to 255. Since you can pick a number between 0 and 100, you can scale that to a range of 0 to 255 by using the formula (n * 255) / 100
. Once you've done that, you determine the appropriate values for red, green, blue, convert to hex, and combine the result into the final hex color:
- Input 0 to 100 from user into
n
. - Calculate normalized value
norm = (n * 255) / 100
. - Set
red
to255 - norm
because it decreases withn
. - Set
green
tonorm
because it increases withn
. - Set
blue
to 0. - Convert
red
,green
,blue
to hexadecimal and concatenate into single string.
Here is a sample implementation in JavaScript that shows the hex color output and also colors the text in that color to demonstrate: http://jsfiddle.net/zEB4J/
Sample images:
Here's a demonstration of generating a gradient: http://jsfiddle.net/XMTcb/
I don't know much about php, but you can solve it without arrays using simple math. lets say x is the number between 0-100. Every color in our RGB must be between 0 and 0xFF (256 possible values), so we should look at x/100 and round it to a fraction with a denominator of 256.
In other words, the fraction: round((x/100)*256)/256
This is the amount of green (00FF00). The amount of red (FF0000) is obviously:
1 - round((x/100)*256)/256
Together, we get the value:
0xFF0000 + round((x/100)*256)/256 * (0x00FF00 - 0xFF0000)
and to if x is an integer, and we want to avoid integer-division rounding, we should evaluate the multiplications before the divisions:
0xFF0000 + (round((x*256)/100) * (0x00FF00 - 0xFF0000)) / 256
and that's the most round evaluation.
The easiest and most versatile way to do this would be 2 functions: one to create a HTML hex value from RGB arrays, and one to fade RGB arrays...
// Creates an HTML HEX color from an array of color integers array(r,g,b)...
function rgb($rgb) {
$ret = '';
foreach ($rgb as $x) {
// Make sure the RGB values are 0-255...
$x = max(0, min(255, $x));
// create a 2 digit hex value for this color component...
$ret .= ($x < 16 ? '0'.dechex($x) : dechex($x));
}
return '#'.$ret;
}
// Returns a fade of $from into $to by $amount ($from and $to are RGB arrays)...
function fade($from, $to, $amount) {
$rgb = array();
// Go through the RGB values and adjust the values by $amount...
for ($i = 0; $i <= 2; $i++) {
$rgb[$i] = (($to[$i] - $from[$i]) * $amount) + $from[$i];
}
return $rgb;
}
Then you could fade any color to any other color by any amount, like this example that fades from red to green with 100 steps...
for ($fadeAmount = 0; $fadeAmount < 1; $fadeAmount += 0.01) {
$color = rgb(fade(array(255,0,0), array(0,255,0), $fadeAmount));
echo "<div style='color:$color'>$fadeAmount</div>";
}
精彩评论