I need to find a way to create colors that lie in between two color values, but in the exact same way e.g. the gradient tool in Photoshop works.
Basicaly I need a to fill a 10 elements array with color values that lie between 2 given colors.
I already found some examples that seperate R, G & B values from a HEX color value and then shift each value seperately, but if I'm not mistaken, that isn't the exact way to create a gradient. Or maybe it is?
anybody an idea on how to approach this?
That's pretty much what you want to do, based on what you've said. As long as you understand that with flash 5 each element in the array will have a solid color. A gradient is just stepping from one color to another gradually, interpolating the values, which is what you're doing. Find the numeric value for each channel. Find the difference between the two channels. Divide the difference by the number of steps, 9 steps for 10 elements. Add or subtract the difference, depending on which channel is < or > to come up with the new color for each channel and apply it with the color object.
You can always compare your gradient against a gradient filled object.
so, you sent me off on a nice little scripting trip...
at first I thought, piece of cake, I'll do it like this:
function create_gradient(color_a,color_b,total){ var difference=(color_b-color_a)/total; var a=0; while(a<total){ attachMovie("box","box"+a,a); var nu=_root["box"+a]; nu._x=a*20; var c=new Color(nu); trace(color_a); c.setRGB(color_a); color_a+=difference; a++; } }
create_gradient(0xFF44EE,0x0044A0,10);
it works, but not correctly.... so, I began to ponder about hexadecimals once again....
I came up with a solution which works with "phony" hexadecimal input (instead of 0xFF33E2, you have to pass the constructor a string containing the key values "FF33E2").
This could be accomplised with a lot less code using rgb values and then using bitwise operations to generate a hexadecimal value... I just decided I wanted to get it to work this way...
so:
//constructor Gradient=function(color_a,color_b,total){ this.cur_color=color_a; this.last_color=color_b; this.total=total; this.increments=this.get_increments(color_a,color_b); }
//converts a "hex pair" to a real number... FF is really 15*15+15 Gradient.prototype.get_hex_parts=function(hex){ var temp=new Array(); var a=0; while(a<6){ var b=hex.charAt(a); var c=hex.charAt(a+1); temp.push(this.get_hex_pos(b)*16+this.get_hex_pos(c)); a+=2; } return temp; }
//generates increments array Gradient.prototype.get_increments=function(color_a,color_b){ var arr_a=this.get_hex_parts(color_a); var arr_b=this.get_hex_parts(color_b); var a=0; var temp=new Array(); while(a<3){ temp[a]=Math.ceil((arr_b[a]-arr_a[a])/this.total); a++; } return temp; }
//converts a string representation of a hexadecimal into a numeric value Gradient.prototype.get_hex_pos=function(str){ var hex=new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"); var a=0; while(hex[a]!=str){ a++; } return a; }
//converts a numeric representation of hexadecimal (0-15) to a "real" hexadecimal number Gradient.prototype.get_hex_char=function(num){ var hex=new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"); return hex[num]; }
//adds the increment value to the hex values Gradient.prototype.increment_col=function(){ var temp=""; var a=0; var inc=0; while(a15){ var c_plus=this.increments[inc]%16; b+=(this.increments[inc]-c_plus)/16; c+=c_plus; }else{ c+=this.increments[inc]; } if(c>15){ c-=16; b++; }else if(c<0){ c+=16; b--; } temp+=(this.get_hex_char(b)+this.get_hex_char(c)); a+=2; inc++; } return temp; }
//draws out the gradient Gradient.prototype.draw=function(){ var a=0; while(a<this.total+1){ _root.attachMovie("box","box"+a,a); var nu=_root["box"+a]; nu._x=a*nu._width; var c=new Color(nu); if(a<this.total){ c.setRGB(parseInt("0x"+this.cur_color)); }else{ c.setRGB(parseInt("0x"+this.last_color)); break; } this.cur_color=this.increment_col(); a++; } }
grad=new Gradient("000000","FF00FF",20); grad.draw();
you need to create a movieclip called "box" which contains any graphic you like I suppose... then this code will duplicate it "total" amount of times from "color_a" to "color_b".
the theory is like this:
if you take colors "FF44DD" and "22BB00", you need to seperate the hexadecimal color values "FF", "44", "DD" and "22","BB","00".
then find the difference between each of the corresponding values and divide it by the total number of iterations in your gradient.
then loop "total" amount of times and increment a "current_color" value by the seperate increment values.

:grumpy: Thanks Sak!! looks great. Next time I see you I'll buy you a beer (Duvelke?).
I'll hold you to it...
(even though I'm sposed to be on a no-beer diet... last year it lasted a few months... we'll see how I do this year
)
maybe jest a good ol fashioned :afro:
i've been working with color and bitwise operators a lot lately, and thought this would be a good exercise. i took the same idea as sakri's code above, and then condensed it with bitwise stuff as per sakri's suggestion
//constructor Gradient = function(hexColorLeft, hexColorRight, intSteps) { this.c1 = hexColorLeft; this.c2 = hexColorRight; this.steps = intSteps;
this.inc = this.getIncrements();
}
// uses the hexColorLeft and
Gradient.prototype.getIncrements = function()
{
var inc = {};
inc.stepR = (((this.c2 >> 16) & 0xFF) - ((this.c1 >> 16) & 0xFF)) / this.steps;
inc.stepG = (((this.c2 >> 8) & 0xFF) - ((this.c1 >> 8) & 0xFF)) / this.steps;
inc.stepB = ((this.c2 & 0xFF) - (this.c1 & 0xFF)) / this.steps;
return inc;
}
//gets the hex value of the current step
Gradient.prototype.getStepColor = function(intStep)
{
var r = (this.c1 >> 16) & 0xFF;
var g = (this.c1 >> 8) & 0xFF;
var b = this.c1 & 0xFF;
r += this.inc.stepR * intStep;
g += this.inc.stepG * intStep;
b += this.inc.stepB * intStep;
return r << 16 | g << 8 | b;
}
//draws out the gradient Gradient.prototype.draw=function(mcShape, mcTarget, intX, intY, intWidth, intHeight) { for(var i=0; i<this.steps; i++) { mcTarget.attachMovie(mcShape, "grad"+i, i); var m = mcTarget["grad" + i];
m._width = Math.round(intWidth / this.steps);
m._height = intHeight;
m._x = intX + (m._width * i);
m._y = intY;
col = new Color(m);
col.setRGB(this.getStepColor(i));
}
}
g = new Gradient(0x990000, 0x000099, 25); g.draw("box", _root, 100, 100, 400, 30);
i was having fun with the old Flash 5 stuff so i took it a step further. this code will act in similar fashion to MX's beginGradientFill() method, allowing you to specify multiple colors, including percentage ratio of where they are placed and alpha settings for each.//constructor Gradient = function(name, colors, alphas, ratios, depth) { this.steps = 100;
this.name = name;
this.depth = depth;
this.colors = colors;
this.alphas = alphas;
this.ratios = ratios;
}
// uses the hexColorLeft and
Gradient.prototype.getIncrements = function(hexColor1, hexColor2, intSteps)
{
var inc = {};
inc.stepA = (((hexColor2 >> 24) & 0xFF) - ((hexColor1 >> 24) & 0xFF)) / intSteps;
inc.stepR = (((hexColor2 >> 16) & 0xFF) - ((hexColor1 >> 16) & 0xFF)) / intSteps;
inc.stepG = (((hexColor2 >> 8) & 0xFF) - ((hexColor1 >> 8) & 0xFF)) / intSteps;
inc.stepB = ((hexColor2 & 0xFF) - (hexColor1 & 0xFF)) / intSteps;
return inc;
}
//gets the hex value of the current step Gradient.prototype.getStepColors = function(hexColor1, objIncrements, intStep) { var ai = (hexColor1 >> 24) & 0xFF; var ri = (hexColor1 >> 16) & 0xFF; var gi = (hexColor1 >> 8) & 0xFF; var bi = hexColor1 & 0xFF;
ai += objIncrements.stepA * intStep;
ri += objIncrements.stepR * intStep;
gi += objIncrements.stepG * intStep;
bi += objIncrements.stepB * intStep;
var c = {a:ai, r:ri, g:gi, b:bi};
return c;
}
//draws out the gradient taking into account the multiple colors and ratios Gradient.prototype.draw = function(mcShape, mcTarget, intX, intY, intWidth, intHeight) { for(var i=0; i<this.colors.length - 1; i++) { var a1 = this.alphas[i]; var a2 = this.alphas[i+1];
var c1 = a1 << 24 | this.colors[i];
var c2 = a2 << 24 | this.colors[i+1];
var r1 = Math.floor((this.ratios[i] * .01) * this.steps);
var r2 = Math.floor((this.ratios[i+1] * .01) * this.steps);
var inc = this.getIncrements(c1, c2, r2-r1);
for(var j=r1; j<r2; j++)
{
var step = (j-r1);
mcTarget.attachMovie(mcShape, this.name + i + "_" + j, ++this.depth);
var m = mcTarget[this.name + i + "_" + j];
m._width = Math.round(intWidth / this.steps);
m._height = intHeight;
m._x = intX + (m._width * j);
m._y = intY;
var col = new Color(m);
col.setRGB(0x000000);
var hex = this.getStepColors(c1, inc, step);
var trans = { aa:hex.a, ab:0, ra:0, rb:hex.r, ga:0, gb:hex.g, ba:0, bb:hex.b };
col.setTransform(trans);
}
}
}
//draw a completely solid 3-color gradient, from blue to black to blue colors = [0x336699, 0x000000, 0x336699]; alphas = [100, 100, 100]; ratios = [0, 50, 100];
g = new Gradient("grad1", colors, alphas, ratios, 400); g.draw("box", _root, 10, 10, 400, 30);
//draw a 4 color gradient with varying alpha settings colors = [0x808080, 0x55FF00, 0x00FF55, 0x808080]; alphas = [100, 20, 100, 20]; ratios = [0, 20, 80, 100];
g = new Gradient("grad2", colors, alphas, ratios, 600); g.draw("box", _root, 10, 40, 400, 30);
//draw a color spectrum colors = [0xFF0000, 0xFFFF00, 0x00FFFF, 0x0000FF, 0xFF00FF, 0xFF0000]; alphas = [100, 100, 100, 100, 100, 100]; ratios = [0, 20, 40, 60, 80, 100];
g = new Gradient("grad3", colors, alphas, ratios, 800); g.draw("box", _root, 10, 70, 400, 30);
bitwise ops are fun!
fantastic code there jimmyn!!!!! :grumpy: :grumpy:
I was gonna come back and recode that sucker with decimal rgb numbers.... but looks like you've done the dirty work!!!
again, nice stuff!!!!! (particularily that second one :notworthy )
:batman: :batman: :batman: :batman:
ok, I've just spent another good 10 minutes re-staring and analyzing your code.... I have to reiterate how impressed I am!!!!!!!
:buttrock::buttrock::buttrock:YOU RAWK!!!!! :buttrock::buttrock::buttrock::buttrock:
thanks!
my stuff was built off your code though, so i'd like to say we both rawk!
:grumpy:
And you've both been very helpful to me :bowdown:
check this out... I was just cleaning out a drawer, where I found a stack of papers... about a year ago I had printed the infamous "more flash5 functions" thread from were-here... I happened to flip through it, and I saw this:
col=0xFFFFFF; trace(col.toString(16));
/*output =
ffffff
*/
this means that in my example, I could accept real hexadecimal numbers in the constructor then simply convert them to strings using the toString(16);...
...and flux... here it's : notworthy :
:notworthy:

yeah! the toString() method is a pleasant actionscript gift (it can also be used in javascript) which makes it unnecessary to use conversion methods anymore.
one thing to be wary of though....normally we use hex values as a two-character representation (FF, 9A, 04, 00), but if the value is less than 16 (F0 in hex), the method only returns one number and leaves out the preceding 0.
i wrote this method yesterday to answer flux's question from the first post in this threadfunction getGradientArrayValues(hexColor1, hexColor2, intSteps) { // create a new array var a = [];
// get the integer values for RGB of the first color
var r1 = (hexColor1 >> 16) & 0xFF;
var g1 = (hexColor1 >> 8) & 0xFF;
var b1 = hexColor1 & 0xFF;
// get the integer values for RGB of the second color
var r2 = (hexColor2 >> 16) & 0xFF;
var g2 = (hexColor2 >> 8) & 0xFF;
var b2 = hexColor2 & 0xFF;
// get the float step value foreach channel
var stepR = (r2 - r1) / intSteps;
var stepG = (g2 - g1) / intSteps;
var stepB = (b2 - b1) / intSteps;
for(var i=0; i<=intSteps; i++)
{
// create a new hexcolor string
var s = "0x";
// calculate the current integer color by adding the step * stepNumber to the first color
var cr = r1 + stepR * i;
var cg = g1 + stepG * i;
var cb = b1 + stepB * i;
// build the string taking into account numbers < 16
s += (cr > 16) ? cr.toString(16) : "0" + cr.toString(16);
s += (cg > 16) ? cg.toString(16) : "0" + cg.toString(16);
s += (cb > 16) ? cb.toString(16) : "0" + cb.toString(16);
// push the string into the array
a.push(s);
}
// return the array
return a;
}
gradient = getGradientArrayValues(0x2200FF, 0xFF66E5, 25);note these lines:
s += (cr > 16) ? cr.toString(16) : "0" + cr.toString(16);
s += (cg > 16) ? cg.toString(16) : "0" + cg.toString(16);
s += (cb > 16) ? cb.toString(16) : "0" + cb.toString(16);
basically before i call toString(), i check if the value is greater than 16. if so, excellent, else i prefix the value with 0.
this can cause real havoc because if we are really looking for the value 0x0E0E0E, without performing the check and prefixing 0, the result string will be 0XEEE.
toString() can accept other radix values as well, such as 8 for octal numbers, or 2 for binary.
awesome:woohoo:
I just bumbed into this... thought it was neat, wanted to add it to this thread, then I realized jimmyn's last post was way über keeeewler than this... but posted it anyway :p
function get_random_color_string(){ var red=Math.round(Math.random()*255); var green=Math.round(Math.random()*255); var blue=Math.round(Math.random()*255); return "0x"+(red.toString(16)+green.toString(16)+blue.toString(16)).toUpperCase(); }
trace(get_random_color_string());
returns a hex string version of rgb figures.