I'm sorry for the bad title (edit if you wish), but I don't know how to put this request. I attached an image from Photoshop that illustrates things a little bit better.
The request itself is quite simple: You have a numeric range from 10.0 to 0.0. 10 stands for the color #00ff00 (deep green) and 0.0 for the color #ff0000 (deep red).
Now, when you hand over the number 10.0 it will output #00ff00. When you give it something like 8.2 it would output something like #00cc33 so that you have a floating gradient all the way down but always float from #00ff00 over orange #ff9900 to #ff0000 (orange in the middle could also be omitted).
I'm sorry for the bad title (edit if you wish), but I don't know how to put this request. I attached an image from Photoshop that illustrates things a little bit better.
The request itself is quite simple: You have a numeric range from 10.0 to 0.0. 10 stands for the color #00ff00 (deep green) and 0.0 for the color #ff0000 (deep red).
Now, when you hand over the number 10.0 it will output #00ff00. When you give it something like 8.2 it would output something like #00cc33 so that you have a floating gradient all the way down but always float from #00ff00 over orange #ff9900 to #ff0000 (orange in the middle could also be omitted).
Share Improve this question edited Jan 28, 2013 at 12:20 asked Jan 27, 2013 at 19:40 user659025user659025 2- 3 I don't think there is a single answer to your question. It really depends on how you want to go from one color range to another, because in the example you gave, there isn't a single range, there are two, for Red and Green. Therefore, you need to define the rules by which you want to transition from one range to another. According to your screenshot, these rules might be defined by the Gradient Type and the Smoothness. And you need rules that can acodate three ranges, one for each color (Red, Green, and Blue). In some cases, you might even need four ranges (CMYK). – Ismael Ghalimi Commented Jan 27, 2013 at 19:45
- It may be helpful for us if you told us why you need to do this in the first place, also. – jeremy Commented Jan 27, 2013 at 19:46
5 Answers
Reset to default 4One way is to think of the colours like a segment of a circle and then make use of Math.cos
or Math.sin
.
function toColour(x) {
var pad = function (x) {
x = x.toString(16);
if (x.length === 1) {
return '0' + x;
}
return x;
}, r, g, b;
r = ~~(255 * Math.cos(Math.PI * x / 20)); // cos(0) = 1, cos(π/2) = 0
g = ~~(255 * Math.sin(Math.PI * x / 20)); // sin(0) = 0, sin(π/2) = 1
b = 0;
return '#' + pad(r) + pad(g) + pad(b);
}
// test the gradient produced
for (var i = 0; i <= 10; ++i) {
document.body.appendChild(
document.createElement('div')
).setAttribute('style', 'width: 400px;height: 5px;background: '+toColour(i)+';');
}
See this fiddle for test results (thanks to MikeM)
Just for fun:
function toHex( n ) {
var r = 255 - ( n / 10 * 255 | 0 );
g = n / 10 * 255 | 0;
return '#' +
( r ? ( r = r.toString(16), r.length == 2 ? r : '0' + r ) : '00' ) +
( g ? ( g = g.toString(16), g.length == 2 ? g : '0' + g ) : '00' ) + '00'
}
See it here (for what its worth): http://jsfiddle/xD6Uf/
Update
Inspired by Samuel Edwin Ward's use of HSL, the following function adapts hslToRgb
from Brian Grinstead's MIT Licensed tinycolor.js:
Note: this function is not intended to be the finished article or represent good practice, it is a proof of concept only. There is no bounds checking and few concessions to readability.
n
is a value from 0 to 10, and start
, middle
and end
are each a hue value from 0 - 360.
See Mother-effing hsl to select hue, saturation and lightness values to experiment with.
function toHex( n ) {
var r, g, b, p, q,
start = 0, // 0 - 360 (red 0)
middle = 36, // 0 - 360 (orange 36, use 0 or null for no middle)
end = 120, // 0 - 360 (green 120)
saturation = 1, // 0 - 1
lightness = 0.5, // 0 - 1
hue = ( middle ?
n > 5 ? ( n -= 5, n / 5 * ( end - middle ) ) + middle :
( n / 5 * ( middle - start ) ) + start :
( n / 10 * ( end - start ) ) + start ) / 360;
function hue2hex( p, q, h ){
if ( h < 0 ) h++;
else if ( h > 1 ) h--;
h = ( h < 1/6 ? p + ( q - p ) * 6 * h : h < 1/2 ? q :
h < 2/3 ? p + ( q - p ) * ( 2/3 - h ) * 6 : p ) * 255 | 0;
return h ? ( h = h.toString(16), h.length > 1 ? h : '0' + h ) : '00';
}
if ( saturation === 0 ) {
n = lightness * 255 | 0;
r = g = b = n ?
( n = n.toString(16), n.length > 1 ? n : '0' + n ) : '00';
} else {
q = lightness < 0.5 ? lightness * ( 1 + saturation ) :
lightness + saturation - lightness * saturation;
p = 2 * lightness - q;
r = hue2hex( p, q, hue + 1/3 );
g = hue2hex( p, q, hue );
b = hue2hex( p, q, hue - 1/3 );
}
return '#' + r + g + b;
}
Example
toHex(0); // "#ff0000"
toHex(5); // "#ff9900"
toHex(10); // "#00ff00"
jsfiddle
It looks like you want to interpolate between colors.
You could just take the color values to be numbers and do an interpolation between them, but I think the results would be very odd.
You'll probably want to convert your colors from RGB to another color space and scale the hue ponent(s). HSL would be a nice choice because CSS3 supports specifying colors in that space.
I put code for both approaches up on jsfiddle.
These are the important parts:
/* numeric interpolation */
for (var value = 0; value < 10; value += 10/40) {
var color = (10-value)/10*(0xff0000-0xff00)+(0x00ff00),
hex = Math.floor(color).toString(16);
while (hex.length < 6) {
hex = "0" + hex;
}
/* hex now holds the hex code */
}
/* hue interpolation */
for (var value = 0; value < 10; value += 10/40) {
var hue = value/10*120, /* red is 0; green is 120 */
color = 'hsl(' + hue + ', 100%, 50%)';
/* hsl now holds the hsl color specification */
}
If you like you can use a fancier approach to interpolating the values than the simple linear formula I used (where x is the input scale and y is the output scale):
y = (x - minX) / (maxX - minX) * (maxY-minY) + minY
So basically you have some range in hex with two variables:
var startHex = "0x00ff00";
var endHex = "0xff0000"
int startInt = parseInt(startHex, 16);
int endInt = parseInt(endHex, 16);
int newInt = startInt + (endInt-startInt)/100 * floatValue; // floatValue is number between 10.0 and 0.0
var newHex = newDec.ToString(16);
I am assuming you intended for 100 increments possible between start and end. This could be done much more cleanly, but for illustration I broke it all out. In practice I would write this in 1-2 lines.
If you want to rely on the browser's rendering engine, you could use HTML5's canvas and createLinearGradient
. One advantage of this approach is the ability to use color stops (though you could do this mathematically if you really wanted also).
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.height = 100; canvas.width = 1;
var gradient = context.createLinearGradient(0,0,0,100);
// color stops
gradient.addColorStop(0, '#00ff00');
gradient.addColorStop(0.5, '#ff9900');
gradient.addColorStop(1, '#ff0000');
context.fillStyle = gradient;
context.fillRect(0,0,1,100);
var point = 10.0,
colorData = context.getImageData(0, parseInt(point*canvas.height*.1, 10), 1, 1).data;
// rgba ( colorData[0], colorData[1], colorData[2], colorData[3] )
You can find the exact rgba coordinates of the color in colorData[0]
(red), colorData[1]
(blue), colorData[2]
(green) and then easily convert those to hex values.
If you end up using this solution, set point
to a number in the range of 0 to 9.9.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745121794a4612457.html
评论列表(0条)