/** * Draw is a static toolbox class that provides a number of functions * to draw shapes that are not part of the standard ActionScript Drawing * API. * * To call this code from the timeline you must include this class in the * classpath in the publish settings menu. * * File -> Publish Settings (Ctrl+Shift+F12 on windows) * - Click "Flash" tab * - Set ActionScript Version to "ActionScript 2.0" or higher... * - Click "Settings" * - click the target icon and select the directory you've extracted * - this code into. You should select the directory that has * - the com directory in it. NOT the directory * - that has the Draw.as file. * * based on source code found at: * http://www.macromedia.com/devnet/mx/flash/articles/adv_draw_methods.html * * @author Ric Ewing - version 1.4 - 4.7.2002 * @author Kevin Williams - version 2.0 - 4.7.2005 */ class com.polymercode.Draw { /** * * This class has all static functions. To call them simply call * com.polymercode.Draw.functionName(parameters); * * You should never have to call new Draw(); * */ private function Draw(){} /** * dashTo * Draws a dashed line from the point x1,y1 to the point x2,y2 * The line may is drawn on the movie clips specified by the * target parameter (default is _root). The line may * be any color or transparency and width, length of dashes, * and space between dashes may all be specified. * * @param target MovieClip the movie clip on which the dashed * line will be drawn. * @param x1 Number starting position on x axis - required * @param y1 Number starting position on y axis - required * @param x2 Number finishing position on x axis - required * @param y2 Number finishing position on y axis - required * @param dashLength [optional] Number the number of pixels long each dash * will be. Default = 5 * @param spaceLength [optional] Number the number of pixels between each * dash. Default = 5 * @param strokWidth [optional] Number the width of each dash. * Default = 1 * @param rgbHex [optional] the Hex color value of the dashed line. * Default = 0x000000 * @param alpha [optional] Number the alpha transparancy that the dashed * line will have. Default = 100; */ public static function dashTo(target:MovieClip, x1:Number, y1:Number,x2:Number, y2:Number, dashLength:Number, spaceLength:Number,strokeWidth:Number,rgbHex:Number ):Void { trace("com.polymercode.Draw.dashTo - arguments:"+arguments); if ( arguments < 5 ){ trace("com.polymercode.Draw.dashTo - too few parameters."); return; } if ( spaceLength == undefined ){ spaceLength = 5; } if ( dashLength == undefined ){ dashLength = 5; } if ( strokeWidth == undefined ){ strokeWidth = 1; } if ( rgbHex == undefined ){ rgbHex = 0x000000; } //added to this target.lineStyle(strokeWidth,rgbHex); var x = x2 - x1; var y = y2 - y1; var hyp = Math.sqrt((x)*(x) + (y)*(y)); var units = hyp/(dashLength+spaceLength); var dashSpaceRatio = dashLength/(dashLength+spaceLength); var dashX = (x/units)*dashSpaceRatio; var spaceX = (x/units)-dashX; var dashY = (y/units)*dashSpaceRatio; var spaceY = (y/units)-dashY; target.moveTo(x1, y1); while (hyp > 0) { x1 += dashX; y1 += dashY; hyp -= dashLength; if (hyp < 0) { x1 = x2; y1 = y2; } target.lineTo(x1, y1); x1 += spaceX; y1 += spaceY; target.moveTo(x1, y1); hyp -= spaceLength; } target.moveTo(x2, y2); } /** * Draws an arc from the starting position of x,y. * * @param target the movie clip that the Arc is drawn on. * @param x x coordinate of the starting pen position * @param y y coordinate of the starting pen position * @param radius radius of Arc. * @param arc = sweep of the arc. Negative values draw clockwise. * @param startAngle = [optional] starting offset angle in degrees. * @param yRadius = [optional] y radius of arc. if different than * radius, then the arc will draw as the arc of an oval. * default = radius. * * Based on mc.drawArc by Ric Ewing. * the version by Ric assumes that the pen is at x:y before this * method is called. I explictily move the pen to x:y to be * consistent with the behaviour of the other methods. */ public static function arcTo(target:MovieClip, x:Number, y:Number, radius:Number, arc:Number, startAngle:Number, yRadius:Number):Void { if (arguments.length<5) { trace("com.polymercode.Draw.arcTo - too few parameters."); return; } // if startAngle is undefined, startAngle = 0 if( startAngle == undefined ){ startAngle = 0; } // if yRadius is undefined, yRadius = radius if (yRadius == undefined) { yRadius = radius; } // Init vars var segAngle, theta, angle, angleMid, segs, ax, ay, bx, by, cx, cy; // no sense in drawing more than is needed :) if (Math.abs(arc)>360) { arc = 360; } // Flash uses 8 segments per circle, to match that, we draw in a maximum // of 45 degree segments. First we calculate how many segments are needed // for our arc. segs = Math.ceil(Math.abs(arc)/45); // Now calculate the sweep of each segment segAngle = arc/segs; // The math requires radians rather than degrees. To convert from degrees // use the formula (degrees/180)*Math.PI to get radians. theta = -(segAngle/180)*Math.PI; // convert angle startAngle to radians angle = -(startAngle/180)*Math.PI; // find our starting points (ax,ay) relative to the secified x,y ax = x-Math.cos(angle)*radius; ay = y-Math.sin(angle)*yRadius; // if our arc is larger than 45 degrees, draw as 45 degree segments // so that we match Flash's native circle routines. if (segs>0) { target.moveTo(x,y); // Loop for drawing arc segments for (var i = 0; i2) { // init vars var step, halfStep, qtrStep, start, n, dx, dy, cx, cy; // calculate length of sides step = (Math.PI*2)/sides; halfStep = step/2; qtrStep = step/4; // calculate starting angle in radians start = (angle/180)*Math.PI; target.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius)); // draw curves for (n=1; n<=sides; n++) { cx = x+Math.cos(start+(step*n)-(qtrStep*3))*(innerRadius/Math.cos(qtrStep)); cy = y-Math.sin(start+(step*n)-(qtrStep*3))*(innerRadius/Math.cos(qtrStep)); dx = x+Math.cos(start+(step*n)-halfStep)*innerRadius; dy = y-Math.sin(start+(step*n)-halfStep)*innerRadius; target.curveTo(cx, cy, dx, dy); cx = x+Math.cos(start+(step*n)-qtrStep)*(innerRadius/Math.cos(qtrStep)); cy = y-Math.sin(start+(step*n)-qtrStep)*(innerRadius/Math.cos(qtrStep)); dx = x+Math.cos(start+(step*n))*outerRadius; dy = y-Math.sin(start+(step*n))*outerRadius; target.curveTo(cx, cy, dx, dy); } } } /** * draws a gear shape on the MovieClip target. The gear position * is indicated by the x and y arguments. * * @param target MovieClip on which the gear is to be drawn. * @param x x coordinate of the center of the gear * @param y y coordinate of the center of the gear * @param sides number of teeth on gear. (must be > 2) * @param innerRadius radius of the indent of the teeth. * @param outerRadius outer radius of the teeth. * @param angle = [optional] starting angle in degrees. Defaults to 0. * @param holeSides [optional] draw a polygonal hole with this many sides (must be > 2) * @param holeRadius [optional] size of hole. Default = innerRadius/3. * * based on mc.drawGear() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002 */ public static function gear(target:MovieClip, x:Number, y:Number, sides:Number, innerRadius:Number, outerRadius:Number, angle:Number, holeSides:Number, holeRadius:Number ):Void { if(arguments<6){ trace("com.polymercode.Draw.gear - too few parameters"); return; } if ( angle == undefined ) angle = 0; if ( holeSides == undefined ) holeSides = 0; if (sides>2) { // init vars var step, qtrStep, start, n, dx, dy; // calculate length of sides step = (Math.PI*2)/sides; qtrStep = step/4; // calculate starting angle in radians start = (angle/180)*Math.PI; target.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius)); // draw lines for (n=1; n<=sides; n++) { dx = x+Math.cos(start+(step*n)-(qtrStep*3))*innerRadius; dy = y-Math.sin(start+(step*n)-(qtrStep*3))*innerRadius; target.lineTo(dx, dy); dx = x+Math.cos(start+(step*n)-(qtrStep*2))*innerRadius; dy = y-Math.sin(start+(step*n)-(qtrStep*2))*innerRadius; target.lineTo(dx, dy); dx = x+Math.cos(start+(step*n)-qtrStep)*outerRadius; dy = y-Math.sin(start+(step*n)-qtrStep)*outerRadius; target.lineTo(dx, dy); dx = x+Math.cos(start+(step*n))*outerRadius; dy = y-Math.sin(start+(step*n))*outerRadius; target.lineTo(dx, dy); } // This is complete overkill... but I had it done already. :) if (holeSides>2) { if(holeRadius == undefined) { holeRadius = innerRadius/3; } step = (Math.PI*2)/holeSides; target.moveTo(x+(Math.cos(start)*holeRadius), y-(Math.sin(start)*holeRadius)); for (n=1; n<=holeSides; n++) { dx = x+Math.cos(start+(step*n))*holeRadius; dy = y-Math.sin(start+(step*n))*holeRadius; target.lineTo(dx, dy); } } } } /** * oval draws used to draw circles or ovals. * According to Ric Ewing -
This method, like most of * the others, is not as optimized as it could be. This was a * conscious decision to keep the code as accessible as * possible for those either new to AS or to the math * involved in plotting points on a curve.
* * @param target the MovieClip that the oval/circle is drawn on. * @param x x coordinate of the center of the oval/circle * @param y y coordinate of the center of the oval/circle * @param radius the radius of the oval/circle * @param yRadius [optional] y radius of the oval. if not defined * then yRadius = radius and therefore, it draws a circle. * * based on mc.drawOval() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002 */ public static function oval(target:MovieClip, x:Number, y:Number, radius:Number, yRadius:Number):Void { if (arguments.length<4) { trace("com.polymercode.Draw.oval - too few parameters"); return; } // if only yRadius is undefined, yRadius = radius if (yRadius == undefined) { yRadius = radius; } // init variables var theta, xrCtrl, yrCtrl, angle, angleMid, px, py, cx, cy; // covert 45 degrees to radians for our calculations theta = Math.PI/4; // calculate the distance for the control point xrCtrl = radius/Math.cos(theta/2); yrCtrl = yRadius/Math.cos(theta/2); // start on the right side of the circle angle = 0; target.moveTo(x+radius, y); // 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)*xrCtrl; cy = y+Math.sin(angleMid)*yrCtrl; // calculate our end point px = x+Math.cos(angle)*radius; py = y+Math.sin(angle)*yRadius; // draw the circle segment target.curveTo(cx, cy, px, py); } } /** * a method for creating polygon shapes. Negative values will draw * the polygon in reverse direction. Negative drawing may be useful * for creating knock-outs in masks. * * @param target the MovieClip that the polygon is to be drawn on * @param x x coordinate of the center of the polygon * @param y y coordinate of the center of the polygon * @param sides the number of sides (must be > 2) * @param radius the radius from the center point to the points * on the polygon * @param angle [optional] the starting offset angle (degrees) from * 0. Default = 0 * * based on mc.drawPoly() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002 */ public static function polygon(target:MovieClip, x:Number, y:Number, sides:Number, radius:Number, angle:Number):Void { if (arguments.length<5) { trace("com.polymercode.Draw.polygon - too few parameters"); return; } if ( angle == undefined ) angle = 0; // convert sides to positive value var count = Math.abs(sides); // check that count is sufficient to build polygon if (count>2) { // init vars var step, start, n, dx, dy; // calculate span of sides step = (Math.PI*2)/sides; // calculate starting angle in radians start = (angle/180)*Math.PI; target.moveTo(x+(Math.cos(start)*radius), y-(Math.sin(start)*radius)); // draw the polygon for (n=1; n<=count; n++) { dx = x+Math.cos(start+(step*n))*radius; dy = y-Math.sin(start+(step*n))*radius; target.lineTo(dx, dy); } } } /** * roundedRectangle draws rectangles with rounded corners. * This is similar to the Flash rectangle tool. If the * rectangle is smaller in either dimension than the * rounding permits then rounding is scaled down to fit * * @param target the MovieClip that the rouded rectangle is to be * drawn on. * @param x x coordinate of the top left corner of the rectangle * @param y y coordinate of the top right corner of the rectangle * @param width width of the rectangle * @param height height of the rectangle * @param cornerRadius the radius of the rounding of the corners of * the rectangle. [optional] * * based on mc.drawRect() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002 */ public static function roundedRectangle(target:MovieClip, x:Number, y:Number, width:Number, height:Number, cornerRadius:Number ):Void { if ( arguments.length<5 ) { trace("com.polymercode.Draw.roundedRectangle - too few parameters"); return; } if ( cornerRadius == undefined ) cornerRadius = 0; // if the user has defined cornerRadius our task is a bit more complex. :) if (cornerRadius>0) { // init vars var theta, angle, cx, cy, px, py; // make sure that w + h are larger than 2*cornerRadius if (cornerRadius>Math.min(width, height)/2) { cornerRadius = Math.min(width, height)/2; } // theta = 45 degrees in radians theta = Math.PI/4; // draw top line target.moveTo(x+cornerRadius, y); target.lineTo(x+width-cornerRadius, y); //angle is currently 90 degrees angle = -Math.PI/2; // draw tr corner in two parts cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); angle += theta; cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); // draw right line target.lineTo(x+width, y+height-cornerRadius); // draw br corner angle += theta; cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); angle += theta; cx = x+width-cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+width-cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); // draw bottom line target.lineTo(x+cornerRadius, y+height); // draw bl corner angle += theta; cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); angle += theta; cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+height-cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+height-cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); // draw left line target.lineTo(x, y+cornerRadius); // draw tl corner angle += theta; cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); angle += theta; cx = x+cornerRadius+(Math.cos(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); cy = y+cornerRadius+(Math.sin(angle+(theta/2))*cornerRadius/Math.cos(theta/2)); px = x+cornerRadius+(Math.cos(angle+theta)*cornerRadius); py = y+cornerRadius+(Math.sin(angle+theta)*cornerRadius); target.curveTo(cx, cy, px, py); } else { // cornerRadius was not defined or = 0. This makes it easy. target.moveTo(x, y); target.lineTo(x+width, y); target.lineTo(x+width, y+height); target.lineTo(x, y+height); target.lineTo(x, y); } } /** * start draws a star shaped polygon. * *
Note that the stars by default 'point' to * the right. This is because the method starts drawing * at 0 degrees by default, putting the first point to * the right of center. Negative values for points * draws the star in reverse direction, allowing for * knock-outs when used as part of a mask.
* * @param x x coordinate of the center of the star * @param y y coordinate of the center of the star * @param points the number of points on the star * @param innerRadius the radius of the inside angles of the star * @param outerRadius the radius of the outside angles of the star * @param angle [optional] the offet angle that the start is rotated * @param target the MovieClip that the star is drawn on * * based on mc.drawStar() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002 */ public static function star(target:MovieClip, x:Number, y:Number, points:Number, innerRadius:Number, outerRadius:Number, angle:Number ):Void { if( arguments.length < 6) { trace("com.polymercode.Draw.star - too few parameters"); return; } if( angle == undefined ) angle = 0; var count = Math.abs(points); if (count>2) { // init vars var step, halfStep, start, n, dx, dy; // calculate distance between points step = (Math.PI*2)/points; halfStep = step/2; // calculate starting angle in radians start = (angle/180)*Math.PI; target.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius)); // draw lines for (n=1; n<=count; n++) { dx = x+Math.cos(start+(step*n)-halfStep)*innerRadius; dy = y-Math.sin(start+(step*n)-halfStep)*innerRadius; target.lineTo(dx, dy); dx = x+Math.cos(start+(step*n))*outerRadius; dy = y-Math.sin(start+(step*n))*outerRadius; target.lineTo(dx, dy); } } } /** * draws pie shaped wedges. Could be employeed to draw pie charts. * * @param target the MovieClip on which the wedge is to be drawn. * @param x x coordinate of the center point of the wedge * @param y y coordinate of the center point of the wedge * @param startAngle the starting angle in degrees * @param arc the sweep of the wedge. negative values draw clockwise * @param radius the radius of the wedge * @param yRadius [optional] the y axis radius of the wedge. * If not defined, then yRadius = radius. * * based on mc.drawWedge() - by Ric Ewing (ric@formequalsfunction.com) - version 1.4 - 4.7.2002 */ public static function wedge(target:MovieClip, x:Number, y:Number, startAngle:Number, arc:Number, radius:Number, yRadius:Number):Void { if (arguments.length<5) { trace("com.polymercode.Draw.wedge - too few parameters"); return; } // move to x,y position target.moveTo(x, y); // if yRadius is undefined, yRadius = radius if (yRadius == undefined) { yRadius = radius; } // Init vars var segAngle, theta, angle, angleMid, segs, ax, ay, bx, by, cx, cy; // limit sweep to reasonable numbers if (Math.abs(arc)>360) { arc = 360; } // Flash uses 8 segments per circle, to match that, we draw in a maximum // of 45 degree segments. First we calculate how many segments are needed // for our arc. segs = Math.ceil(Math.abs(arc)/45); // Now calculate the sweep of each segment. segAngle = arc/segs; // The math requires radians rather than degrees. To convert from degrees // use the formula (degrees/180)*Math.PI to get radians. theta = -(segAngle/180)*Math.PI; // convert angle startAngle to radians angle = -(startAngle/180)*Math.PI; // draw the curve in segments no larger than 45 degrees. if (segs>0) { // draw a line from the center to the start of the curve ax = x+Math.cos(startAngle/180*Math.PI)*radius; ay = y+Math.sin(-startAngle/180*Math.PI)*yRadius; target.lineTo(ax, ay); // Loop for drawing curve segments for (var i = 0; i