Accessibility

Flash Article

Introduction to Macromedia Flash MX Drawing Methods

Ric Ewing

Ric Ewing www.ricewing.com

In the past, Macromedia Flash presented some limitations if you attempted to draw objects programmatically. Even simple lines required some clever manipulation of pre-drawn movie clips. For more complex objects, the limits were such that only the most adept ActionScript developers could even try-and even they experienced mixed results.

Now, with Macromedia Flash MX, nearly all the capabilities of the built-in drawing tools are available in ActionScript. When you couple that with the power inherent in ActionScript itself, the results can be astounding.

The new drawing methods give the ActionScript author the power to create interactive visual elements that would have been difficult (or even impossible) to do before. You'll find a tour of these drawing methods below. Although this article is a basic introduction and accessible to newcomers, it does assume that you have working knowledge of ActionScript.

Sample files

This article refers to specific files throughout the instructions. Download these sample files to follow along and evaluate the ActionScript.

Windows

drawing_methods.zip (28K)

Macintosh

drawing_methods.sit (28K)

What are draw methods?

The new draw methods are ActionScript commands that are available to every movie clip. These methods allow for the creation of lines and shapes via code at run-time rather than having to rely on pre-drawn graphics. The new methods are:

With these tools you can do just about anything you can do using the Macromedia Flash MX drawing tools. These ActionScript drawing tools bring some new concepts into Flash, so let's cover those first.

The virtual pen

Every movie clip now has what I'll refer to as a virtual "pen." This pen is, by default, located at the movie clip's origin (0,0) and has no set stroke or fill, so it is invisible. The draw methods either modify the pen's properties or move the pen. A simple example of this virtual pen is found in the downloadable sample files. Open the drawLine.fla file to view this example in Macromedia Flash MX. You can also click the "Draw line to 100,75" button in the illustration below to see ActionScript virtual pen at work.


This sample file requires the latest version of the Macromedia Flash Player.

Download it now.

In the movie above, the following ActionScript exists on the button:

on (release) {
                    _root.lineStyle(1, 0x0000FF, 100);
                    _root.lineTo(100, 75);
          }

Because the _root has all the properties of a movie clip, it too has access to the draw methods (for most of the code examples I include in the text, I'll be using _root rather than an instance of a movie clip, so that the code can be used by simply copying and pasting into a frame in Flash). The second line establishes that the pen's line should be 1 pixel in width, blue (defined as a hexadecimal number, just like an HTML page), and the line should be 100 percent opaque. Now that we have established the lineStyle for the pen, the next line puts it to use by drawing a line from the current pen position (which is at the default 0,0) to the specified location of 100,75. After drawing this line, the current pen position is 100,75.

Depth and draw methods

The drawing methods draw behind any content created either manually or via movie clip methods (duplicateMovieClip or attachMovie) within a clip. For example, when we use the draw methods to draw a line, the line will display behind all of the content that exists in that movie clip. Subsequent lines or fills will appear on top of previous draw method objects, but they will still be behind objects created by other means. A closer look at draw methods

Most attempts to categorize items will use an alphabetical system and while this is a perfectly valid way of sorting information, it can lead to confusion when related methods are presented either in reverse order or out of sequence. To avoid this, we'll cover the methods in order of likely usage to avoid circuitous explanations. I'm saving the more complex methods for the end so that by the time we cover them, you'll have had a chance to acquire an understanding of the general concepts behind these new drawing methods.

MovieClip.moveTo(x, y)

This method changes the coordinates of the virtual pen without actually drawing anything. The x and y values are pixel coordinates for the movie clip. Particulars: This is the equivalent of lifting the virtual pen and setting it in a new location on the movie clip without drawing a line. For example, if in our above SWF file we wanted to draw the line from 140,20 to 100,75, we would need to add one line of code:

on (release) {
                    _root.lineStyle(1, 0x0000FF, 100);
                    _root.moveTo(140,20);
                    _root.lineTo(100, 75);
          }

An example of this is found in the downloadable sample files. Open the file moveTo.fla to view this example in Macromedia Flash MX. Here's the working example:


This sample file requires the latest version of the Macromedia Flash Player.

Download it now.

Note that even with the pen set to having a line and color, the moveTo does not draw anything. One caveat to this example is that it will draw a new line every time you press the button. This means that if a user were to sit and tap the button repeatedly (say, more than 2000 times), the SWF would continue to increase its memory usage until it could potentially bog down your browser. Obviously, any user doing that desperately needs a hobby, but it's best to try to avoid these repetitive situations by managing the initial situation. We can control this by using another method, MovieClip.clear, discussed further on.

MovieClip.lineStyle(thickness, rgb, alpha)

This method sets the properties for the virtual pen's line. We've seen it used already, but let's go over the parameters:

Thickness:

This sets the width of the line drawn. The thickness defaults to "undefined," which is the equivalent of having no line. Despite the fact that the drawing tools in the application have a thickness which is adjustable in .25-point increments, the lineStyle is limited to integers from 0 to 255. Values greater than 255 are treated as 255 and values less than 0 are treated as 0. A potential surprise is that setting the thickness to 0 does not turn off the pen's line-rather it sets the thickness to "hairline," which always renders as 1 pixel in width (even when scaled). To stop the pen from drawing lines, you can simply call lineStyle with no parameters to turn it off.

RGB:

This sets the color of the line, and is defined as a hexadecimal number (just like the hexadecimal numbers you would use for defining colors in HTML). For example, red is 0xFF0000; green, 0x00FF00; blue, 0x0000FF; white, 0xFFFFFF; and black, 0x000000. If no color is specified, the color is set to black.

Alpha:

This sets the opacity of the line in terms of a percentage. The acceptable values are integers from 0 (completely transparent) to 100 (completely opaque). If no alpha is specified, the default value of 100 is used.

Particulars:

While the lineStyle can take three parameters, the following is perfectly valid ActionScript and is not uncommon usage for the method: Because this code has the first property-thickness-set and because the other parameters have default values, this code will set the line properties for the _root to be a solid black line which is 2 pixels wide. This code is also perfectly acceptable:

  • The moral here is that you shouldn't have to specify more than you really need to. The same is true of some of the other methods we'll see later on. All lines drawn after setting lineStyle are treated as a single object. Calling lineStyle will stop drawing the current line object and begin a new one, even if the parameters are the same. This may cause some unwanted results when using overlapping lines with the alpha set to less than 100. Press and hold the "multiple lineStyles" button in the example below (with the alpha set to 25) to see the change. Open the file lineStyle.fla to view this example in Macromedia Flash MX.


    This sample file requires the latest version of the Macromedia Flash Player.

    Download it now.

    MovieClip.lineTo(x, y)

    This method draws a line from the current pen position to the specified coordinates and leaves the virtual pen at those coordinates. That's really all it does. Particulars: Macromedia Flash MX draws lines in increments called twips, which are 1/20 of a pixel, so you can get precision of 0.05 on your lines. To make a line visible (without scaling it up), the minimum size is 0.15 pixels. Knowing this, and knowing that Macromedia Flash rounds the ends of all lines, you can create a quick and dirty filled circle by setting lineStyle to the desired width of the circle (up to 255) and drawing a 0.15 pixel line at the center of where you want it to display. To draw a 100 pixel wide red circle at 100,100, ActionScript would look something like this:

    _root.lineStyle(100,0xFF0000);
              _root.moveTo(100,100);
              _root.lineTo(100.15,100);

    While this is a clever trick, there are a couple of drawbacks. The first is that if you change the _yscale on the movie clip that contains the red circle, the circle may change position, but will not change shape. This is because it isn't a circle, it is a horizontal line and the height of a horizontal line doesn't change with _yscale. The second is that if you increase the _xscale on the movie clip that contains the red circle, the circle will change position and will scale uniformly larger, based on the _xscale. If you decrease the _xscale on the movie clip that contains the red circle, the circle will disappear. This is because the line that creates the circle drops below the minimum length. This is why the above trick is probably not the best solution for all your circle needs, but in a pinch it's handy to have it up your sleeve. In this example, I've used the lineTo along with another new method, setInterval, to draw a line between two draggable movie clips. This is called lineTo.fla in your folder of sample files.


    This sample file requires the latest version of the Macromedia Flash Player.

    Download it now.

    MovieClip.beginFill(rgb, alpha)

    This method sets the virtual pen's fill properties to the specified color and opacity. RGB: This sets the color of the fill, and is defined as a hexadecimal number-just like the lineStyle method above. If no color is specified, no fill is created and any current fill is closed (connected back to its starting point).

    Alpha:

    This sets the opacity of the fill as a percentage. The acceptable values are integers from 0 (completely transparent) to 100 (completely opaque). If no alpha is specified, the default value of 100 is used. Particulars: Like the lineStyle, this method doesn't require you to specify an alpha value if you want the default solid fill. The fill on its own does not create a fill. It requires the line drawing methods of lineTo or curveTo to define the filled shape boundaries. The fill shape starts and ends at the first point drawn after it is called (either the current pen position or the point specified by a moveTo). This could be used to fill a square shape by only drawing 3 sides, like so…

    _root.beginFill(0x00FF00);
              _root.moveTo(100,100); // this is the origin
              _root.lineTo(200,100);
              _root.lineTo(200,200);
              _root.lineTo(100,200); …but it is highly recommended that you always close your fill shape by making the last line drawn connect back to the shape's origin. Another problem with the above code is that the fill is "left
             on" and will continue to change with each additional lineTo. Another thing that may trip you up is the fact that if you put a moveTo in the middle of code that is drawing a fill, this addition will close that fill and begin a new fill. Try
             this code to see how it works: _root.beginFill(0x00FF00);
              _root.moveTo(100,100); // this is the origin
              _root.lineTo(200,100);
              _root.lineTo(200,200);
              _root.moveTo(100,200); // close the first fill and start a new one
              _root.lineTo(200,300);
              _root.lineTo(100,300);

    Again, this doesn't "turn off" the fill, which brings us to the next method.

    MovieClip.endFill()

    This method takes no parameters and is used to explicitly turn off the fill properties of the pen and close any fill being drawn.

    Particulars:

    While using another beginFill with no parameters effectively does the same thing as endFill, it is bad form to do so. This is true for changing the fill properties while drawing an object as well. I recommend always using endFill to stop the current fill and clear the settings from the pen, rather than counting on a new beginFill to override the previous settings. The above example of drawing a square (which was executed with poor form), would look like this if done correctly:

    _root.beginFill(0x00FF00);
              _root.moveTo(100,100); // this is the origin
              _root.lineTo(200,100);
              _root.lineTo(200,200);
              _root.lineTo(100,200);
              _root.lineTo(100,100); // return to the origin
              _root.endFill(); // stop the fill

    This approach is much cleaner. The following example updates the lineTo example shown above to draw a filled triangle between three points that you can manipulate.


    This sample file requires the latest version of the Macromedia Flash Player.

    Download it now.

    MovieClip.clear()

    This method takes no parameters. It clears all objects created via draw methods from a movie clip, and returns the virtual pen to its default position and settings.

    Particulars:

    One of the potential hazards of programmatic drawing is that our drawings can get extremely complex with very simple code. To prevent this from happening, we can clear out the objects we've drawn to our clip and speed things up again. Of course, the downside is that this is not selective, so if there is anything you've drawn that you want to keep, you'll have to redraw it after you clear the movie clip.


    This sample file requires the latest version of the Macromedia Flash Player.

    Download it now.

    MovieClip.curveTo(controlX, controlY, anchorX, anchorY)

    This method draws a curve from the current pen position to the specified anchor x and y coordinates using the control x and y coordinates to define the magnitude and direction of the curve. Control X and Y: The horizontal and vertical position of the control point for the curve. You can think of this as being equivalent to the control handle for both the start and end points.

    Anchor X and Y:

    The horizontal and vertical position of the end point of the curve. This will be the position of the virtual pen after this method has completed.

    Particulars:

    Every curve in Macromedia Flash, regardless of how it was created, is rendered using Quadratic Bezier curves, but what does that mean? There are a number of ways to draw vector curves, each with their own advantages and limitations. Macromedia Flash uses Quadratic Bezier curves because they render fast and require less data to store. The Quadratic Bezier curve has a start point and an end point, as you would expect, but it only uses a single control point, which affects both ends of the curve. This means that Flash only has to store three points to define the curve.

    Sounds good so far, but there is a caveat to this. They can't actually draw a true circle. The best they can do is approximate one. The more curves you use, the closer the approximation is. Macromedia Flash uses 8 Quadratic Bezier curves to draw circles with its circle tool, which is a close enough approximation for our purposes. The reason I bring this up is that it can trip up folks used to using the Cubic Bezier curves that are found in most PostScript-based vector packages like FreeHand, where 4 curves can define a circle. For those who would like more details, see the TechNote (written for Macromedia Flash 5, but still applicable) that details the use of Quadratic Bezier curves and how they differ from other curves. Seeing as I've brought up circles a number of times, here's some code that draws a 100 pixel-wide circle centered at 200,200. Unlike our quick and dirty version above, it takes some more work (and some tougher math) to do, but the upside is that it is the same as a circle that you draw with the circle tool in Macromedia Flash and will behave as expected.

    var x = 200; // set our x for the center point of the circle
              var y = 200; // set our y for the center point of the circle
              var radius = 50; // radius is half of width so 100/2 = 50.
              var theta = (45/180)*Math.PI; // each segment is 45 degrees, so convert to radians.
              var ctrlRadius = radius/Math.cos(theta/2); // this gets the radius of the control point _root.lineStyle(1); // set our lineStyle
              _root.moveTo(x+radius, y); //we start the circle on the far right side.
              var angle = 0; // start drawing at angle 0;
              // this loop draws the circle in 8 segments
              for (var i = 0; i<8; i++) {
                           // increment our angles
                           angle += theta;
                           angleMid = angle-(theta/2);
                           // calculate our control point
                           cx = x+Math.cos(angleMid)*(ctrlRadius);
                           cy = y+Math.sin(angleMid)*(ctrlRadius);
                           // calculate our end point
                           px = x+Math.cos(angle)*radius;
                           py = y+Math.sin(angle)*radius;
                           // draw the circle segment
                           _root.curveTo(cx, cy, px, py);
              }

    Admittedly, the above code isn't terribly useful as it is, but it should be a good start on drawing your own circles. The example below is a single curve with the three points as handles, which you can drag around to get a feel for how these things work. This is sample file curveTo.fla.


    This sample file requires the latest version of the Macromedia Flash Player.

    Download it now.

    MovieClip.beginGradientFill(fillType, colors, alphas, ratios, matrix)

    This method sets the virtual pen's fill properties to be a gradient as specified by the parameters. If any of the parameters are missing or incorrect, the fill is not set.

    FillType:

    This is a string that says what style of gradient we are using. Acceptable values are "linear" or "radial."

    Colors:

    This is an array of hexadecimal color values that define all the colors used in the gradient. Acceptable values range from 0x000000 to 0xFFFFFF. If the number of elements in the colors array does not match both the number of elements in the alphas array and ratios array, the method will fail and the fill with not be set.

    Alphas:

    This is an array of decimal values that correspond to the opacity of each color defined in the colors array. Acceptable values are from 0 to 100. As above, if the number of elements in alphas does not match both colors and ratios, the method will fail and the fill will not be set.

    Ratios:

    This is an array of values. These values correspond to the placement of each color in the colors array. Acceptable values are from 0 to 255. This is the equivalent of the gradient slider in the Color Mixer in MX. If our gradient is going from left to right, a ratio of 0 would place the corresponding color at the far left, a value of 255 at the far right, and 127 in the middle. Just as above, if the number of elements in the ratios array does not match the color and alphas arrays, the method will fail.

    Matrix:

    This is an object with named variables that define the size, position and rotation of the gradient we want to use. There are two ways to define your matrix. The first is called a 3.x 3 matrix. For the mathematically inclined this may be a familiar, but for the average user this way of defining size, location and rotation is far more confusing and is best left to those who wouldn't need a tutorial on its use. I'll skip this type of matrix for this tutorial, but the documentation within Macromedia Flash MX should be enough for those who want to try this one out for themselves to get started. Fortunately for us, the second method is much more accessible. I've been referring to it as the Box type, and it has the following parameters: matrixType, x, y, w, h, r.

    MatrixType:

    This accepts only one value: a string containing the word "box"-hence the title Box type.

    X and Y:

    These define the top-left coordinate of the gradient.

    W and H:

    These set the horizontal Width and vertical Height of the gradient.

    R:

    This defines the rotation of the gradient in radians, not degrees. For those who need a little help with the math, use the following formula to convert from degrees to radians:

    Radians = (degrees/180)*Math.PI

    The easiest way to define the matrix is to make an object, as follows:

    matrix = { matrixType:"box", x:100, y:100, w:200, h:200, r:(45/180)*Math.PI };

    Particulars:

    Overall, this method can seem a bit overwhelming at first, but it isn't too bad once you've had some experience with it. Rather than try to explain further, here's some code that you can play with to try it out for yourself:

    // create a clip to draw to
              _root.createEmptyMovieClip("mc",1);
              // make a gradient with 6 colors
              colors = [0xFF0000,0xFFFF00,0x00FF00,0x00FFFF,0x0000FF,0xFF00FF];
              // all of the colors should be opaque
              alphas = [100,100,100,100,100,100];
              // these ratios are in hexadeciaml, in even steps from 0 to 255
              ratios = [0x0,0x33,0x66,0x99,0xCC,0xFF];
              // 0 radians is the equivalent of no rotation for the gradient
              radians = 0;
              // build our matrix using the "box" method
              matrix = { matrixType:"box", x:50, y:50, w:200, h:200, r: radians }
              // put all that together in the beginGradientFill
              mc.beginGradientFill("linear",colors,alphas,ratios,matrix);
              // draw the bounding box
              mc.moveTo(50,50);
              mc.lineTo(250,50);
              mc.lineTo(250,250);
              mc.lineTo(50,250);
              mc.lineTo(50,50);
              // close up the fill
              mc.endFill();
    

    One thing to avoid: there is a known bug where if you set the width and height to a small number (approaching 1)-the fills will begin to behave erratically. They will not rotate correctly and will occasionally display incorrectly. This has been the case for gradient fills at least since Macromedia Flash 5, but most users will never encounter this bug as the usefulness of a 1 x 1 gradient is minimal. I mention it only because in experimenting with this method you may run across it.

    Summary

    Hopefully you now have a good grasp of what the ActionScript drawing methods are for and how they work. We've just scratched the surface here of what the new draw methods are capable of doing. Don't let the examples I've included put you off-they are minimalist for the sake of clarity and really don't push the boundaries of what can be done. Given some time, the full usefulness of these powerful new tools will come to light as the Flash community starts exploring the possibilities. Any way you look at it, drawing in Macromedia Flash just became a lot more interesting.


    About the author
    Ric Ewing has been working in software development, interface design, and game design for nearly 15 years. Most recently, he was the Principal Media Architect for Riverdeep (formerly Edmark), where he created award-winning children's educational software for over seven years. For the past two years he has focused primarily on developing streaming educational content for delivery to both home and school markets, with Macromedia Flash being the primary mechanism for delivery.

    Ric's current project is Ric Ewing Design, a web design group that specializes in website development and interactive user experiences. He can be reached at ric@ricewing.com.


  •