Being able to draw gradient fills programmatically is important for many reasons. Some of them are: to accomplish visually interesting gradient effects, to create gradient masks, reflections, and to use DisplacementMapFilter. See for example the reflection effect that requires creating gradients: How to Create a 3D Reflection in AS3 and Flash CS4.

Download

Download the well-commented source file corresponding to the movie above, gradients.fla.

Comments

As you can see, we created four Shapes: rect, circ, ellip, and rainbow, and filled each one with a gradient fill with different parameters. Let us comment first on the main methods used to create gradient fills: Graphics.beginGradientFill and Matrix.createGradientBox. Let's use the Shape 'circ' as an example.

The method 'beginGradientFill' that we use to draw our gradients, for example:

**circ.graphics.beginGradientFill(...);**

takes the following parameters (the first four must be provided):

**beginGradientFill(type:String, colors:Array, alphas:Array, ratios:Array,
matrix:Matrix=null, spreadMethod:String="pad");**

(There are two more optonal parameters: interpolationMethod:String="rgb" and focalPointRation:Number=0. We do not discuss them in this How-To.)

Two possible 'types' with obvious interpretation are GradientType.LINEAR or GradientType.RADIAL. The three Arrays 'colors', 'alphas', and 'ratios' must be of equal length corresponding to the number of colors involved in a gradient fill.

'colors' Array specifies the HEX of each color in the gradient. 'alphas' Array specifies the alpha, that is, the transparency of each color (between 0.0 and 1.0). 'ratios' Array gives the 'ratio' for each color. Each ratio is an integer between 0 and 255 that gives the position along the width, or along the radius, the position at which a given color is at its full saturation. ratio/256 represents the percent of the width (for a linear gradient) or of the radius (for radial gradient) where the color is at its full saturation. Thus, for example, in a linear gradient, ratio=0 for a color means that the color is at 100 percent at the left border of the gradient, ratio=128 means the color is at its full in the center of the gradient, ratio=255 means that the color is at its full at the right border of the gradient. The meaning of 'colors', 'alphas', and 'ratios' becomes very clear with a little bit of experimentation.

The 'matrix' parameter is optional and, by default set to null. However, without using this parameter controlling gradients is practically impossible. Fortunately, without direct matrix manipulation, you can easily create a matrix suitable for your gradient. The method 'createGradientBox' of the Matrix class makes it straightforward. The method Matrix.createGradientBox takes the following parameters:

**createGradientBox(width:Number, height:Number, rotation:Number, translx:Number, transly:Number);**

'gradientBox' is a geometric object in the abstract sense only. 'gradientBox' defines a matrix which used with your gradient fill gives you what you want. 'gradientBox' defines the width and height of your gradient, its rotation (in radians!), and the horizontal and vertical translation of the gradient's center. The width and the height of your gradientBox may be bigger or smaller than the actual dimensions of the Shape in which you are drawing.

The most important feature of the gradientBox is that it gives you precise control
over the gradient's position and its center: the center is at x=width/2, y=height/2. When you draw gradient fill,
the latter two coordinates will be interpreted as ** relative to the registration point of the Shape
in which you are drawing**. See the comments within 'drawShapes' function below to see how it works.

You can accomplish x- and y- scalling of radial gradients by creating a non-quare gradientBox.

If the dimensions of your gradientBox are smaller than of the Shape in which your are drawing, the gradient will spread within your Shape accoriding to the method specified: SpreadMethod.REPEAT, SpreadMethod.PAD, or SpreadMethod.REFLECT.

Code

Below is the code. (We keep comments within the code for the sake of clarity.)

**
/*
We are creating and positioning four Shapes: rect, circ, ellip,
and rainbow. We will draw gradients in these Shapes.
*/
**

var rect:Shape=new Shape();

this.addChild(rect);

rect.x=40;

rect.y=70;

var rectWidth:Number=200;

var rectHeight:Number=100;

var circ:Shape=new Shape();

this.addChild(circ);

circ.x=410;

circ.y=120;

var circRad:Number=50;

var ellip:Shape=new Shape();

this.addChild(ellip);

ellip.x=40;

ellip.y=220;

var ellipWidth:Number=200;

var ellipHeight:Number=100;

var rainbow:Shape=new Shape();

this.addChild(rainbow);

rainbow.x=300;

rainbow.y=250;

var rainbowWidth:Number=200;

var rainbowHeight:Number=50;

**
/*
We are calling the function that draws our gradients.
*/
**

drawShapes();

function drawShapes():void {

var mat:Matrix;

var colors:Array;

var alphas:Array;

var ratios:Array;

**//We proceed to draw 'rect'.**

mat=new Matrix();

colors=[0xFF0000,0x00FF00];

alphas=[1,1];

ratios=[0,255];

**//The center of the gradient is in the center of the 'gradientBox'; that is,**

**//in the case below at x=rectWidth/2, y=rectHeight/2. Those coordinates will**

**//be interpreted as relative to the registration point of the Shape**

**//for which we use 'beginGradientFill' with 'mat' parameter; that is,**

**//relative to 'rect'. Without the 'rotation' parameter, 'toRad(-90)', **

**//in the gradientBox, the gradient would go from left to right.**

mat.createGradientBox(rectWidth,rectHeight,toRad(-90));

rect.graphics.lineStyle();

rect.graphics.beginGradientFill(GradientType.LINEAR,colors,alphas,ratios,mat);

rect.graphics.drawRect(0,0,rectWidth,rectHeight);

rect.graphics.endFill();

**//We proceed to draw the next Shape, 'circ'.**

mat= new Matrix();

colors=[0xFFFFFF,0xFF00FF];

alphas=[1,1];

ratios=[0,255];

**//Without the translation parameters, -circRad+25, -circRad-25, the center**

**//of the gradient will fall at the point x=circRad, y=circRad relative to **

**//the center of the circle. So the center of the gradient will fall in the**

**//lower right portion of the perimeter of the circle. -circRad, -circRad **

**//move the center of the gradient to the center of the circle; the +25 **

**//and -25 parts move it a bit up and to the right.**

mat.createGradientBox(2*circRad,2*circRad,0,-circRad+25,-circRad-25);

circ.graphics.lineStyle();

circ.graphics.beginGradientFill(GradientType.RADIAL,colors,alphas,ratios,mat);

circ.graphics.drawCircle(0,0,circRad);

circ.graphics.endFill();

**//We proceed to draw the next Shape, 'ellip'.**

mat= new Matrix();

colors=[0x9999FF,0x0000FF];

alphas=[1,1];

ratios=[0,255];

**//x- and y- scaling of a radial gradient will automatically happen**

**//if you use a non-square 'gradientBox' for radial gradient, as in**

**//ellip below. The radial gradient will be vertically squeezed**

**//by the factor of 2 as ellipHeight is twice smaller than ellipWidth. **

**//In additon, the size of the gradientBox is smaller than the size of **

**//the ellipse, 'ellip'. The gradient will spread according to **

**//SpreadMethod.REFLECT. Note the translation parameters that move **

**//the center of the gradient to the center of 'ellip'.**

mat.createGradientBox(ellipWidth/4,ellipHeight/4,0,3*ellipWidth/8,3*ellipHeight/8);

ellip.graphics.lineStyle();

ellip.graphics.beginGradientFill(GradientType.RADIAL,colors,alphas,ratios,mat,

SpreadMethod.REFLECT);

ellip.graphics.drawEllipse(0,0,ellipWidth,ellipHeight);

ellip.graphics.endFill();

**//We proceed to draw the next Shape, 'rainbow'.**

mat=new Matrix();

colors=[0xFF0000,0xFFFF00,0x00FF00,0x00FFFF,0x0000FF,0xFF00FF,0xFF0000];

alphas=[1,1,1,1,1,1,1];

**//255/6=42.5, round off is 42. We want to divide 255 long spectrum **

**//into 6 equally spaced pieces to distribute uniformly 7 colors.**

ratios=[0,42,84,126,168,210,255];

mat.createGradientBox(rainbowWidth,rainbowHeight);

rainbow.graphics.lineStyle();

rainbow.graphics.beginGradientFill(GradientType.LINEAR,colors,alphas,ratios,mat);

rainbow.graphics.drawRect(0,0,rainbowWidth,rainbowHeight);

rainbow.graphics.endFill();

}

**
/*
'toRad' helper function converts degrees to radians.
*/
**

function toRad(a:Number):Number {

return a*Math.PI/180;

}

AS3 has another gradient method of the Graphics class: 'lineGradientStyle'. 'lineGradientStyle' method also helps in creating interesting gradient effects. It is a subject for another How-To.