Styling a graph
Until now, we've used the most basic way of drawing points, lines, and areas. However, ActionScript's Graphic
class offers a wealth of different options to make your charts look more attractive.
In this recipe, we will give a short primer of some of the tools at your fingertips. We won't be able to cover them all, but this should help you on your way.
Getting ready
We start by having a graph that shows all three types of charts we've discussed:
package { import flash.display.Sprite; public class Recipe8 extends Sprite { private var graph:Graph; private var data:Array = [[0, 20], [50, 70], [100, 0], [150, 150], [200, 300], [250, 200], [300, 400], [350, 20], [400, 60], [450, 250], [500, 90], [550, 400], [600, 500], [650, 450], [700, 320]]; public function Recipe8() { graph = new Graph( -50, 550, 750, -50); addChild(graph); graph.drawHorizontalAxis(0, 0, 700, 50, ["0", "700"]); graph.drawVerticalAxis(0, 0, 500, 50, ["0", "250", "500"]); graph.drawPoint(data[0][0], data[0][1] + 50); for (var i:Number = 1; i < data.length; i++) { graph.drawArea(data[i - 1][0], data[i - 1][1], data[i][0], data[i][1]); graph.drawLine(data[i - 1][0], data[i - 1][1] + 25, data[i][0], data[i][1] + 25); graph.drawPoint(data[i][0], data[i][1] + 50); } } } }
Notice that we have shifted the y-coordinate of the different charts, so that it's clear which one is which. If you run this program you should see an area chart, 25 pixels higher a line graph, and the another 25 pixels higher a point chart.
How to do it...
- Let's look at points first and replace the points with images.
For this recipe, we will use the freely available SweetiePlus icons, available at http://sublink.ca/icons/sweetieplus/. Copy any one of the icons you would like to the
lib
folder of your project. For instance, the heart icon:heart-16-ns.png
.If you open the folder in FlashDevelop, you should see the file appear. Place the cursor in the
Recipe8
class file, just above the graph'svar
definition.Now right-click on the image and pick generate embed code. This will embed the image into your program and is the easiest and best way to embed small images like this.
Note
If you use some other software, embedding images might be a little different: In Flash Builder you can use the
[Embed]
metadata tag directly. Refer to: http://www.adobe.com/devnet/flash/articles/embed_metadata.html.In Flash Professional, you can also add the resource to the stage and give it an instance name to address it directly without the need for an
[Embed]
tag.Just below the embed code, you now need to connect that embedded image to a class name. It looks like the following code:
… public class Recipe8 extends Sprite { [Embed(source = "../lib/heart-16-ns.png")] private var HeartClass:Class; private var graph:Graph;
We can now add a new
drawBitmapPoint
method to theGraph
class:public function drawBitmapPoint(x:Number, y:Number, BitmapClass:Class):void { var transformedLocation:Point = matrix.transformPoint(new Point(x, y)); var bitmapPoint: Bitmap = new BitmapClass(); bitmapPoint.x = transformedLocation.x - bitmapPoint.width / 2; bitmapPoint.y = transformedLocation.y - bitmapPoint.height / 2; addChild(bitmapPoint); }
- Next we will look at gradients. These allow you to fill an area or a line with a gradually changing color. The complete description of how to apply, position, and create gradients is fairly complicated and beyond the scope of this recipe.
However, we will explain one example, the drawing of a gradient-filled area:
public function drawGradientArea(x1:Number, y1:Number, x2:Number, y2:Number, y3:Number = 0, y4:Number = 0):void { var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y1)); var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y2)); var transformedLocation3:Point = matrix.transformPoint(new Point(x1, y3)); var transformedLocation4:Point = matrix.transformPoint(new Point(x2, y4)); var area:Shape = new Shape(); var gradType:String = GradientType.LINEAR; var colors:Array = [0xff9933, 0x9933ff]; var alphas:Array = [1, 1]; var ratios:Array = [100, 255]; var matrix:Matrix = new Matrix(); matrix.createGradientBox(stage.stageWidth, stage.stageHeight, Math.PI / 2); area.graphics.beginGradientFill(gradType, colors, alphas, ratios, matrix); area.graphics.moveTo(transformedLocation1.x, transformedLocation1.y); area.graphics.lineTo(transformedLocation2.x, transformedLocation2.y); area.graphics.lineTo(transformedLocation4.x, transformedLocation4.y); area.graphics.lineTo(transformedLocation3.x, transformedLocation3.y); area.graphics.endFill(); addChild(area); }
- You can also apply gradients to lines, but for the final example, we'll look at applying bitmaps to lines:
public function drawBitmapLine(x1:Number, y1:Number, x2:Number, y2:Number, BitmapClass:Class):void { var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y1)); var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y2)); var line:Shape = new Shape(); line.graphics.lineStyle(16, 0x000000); var bitmap:Bitmap = new BitmapClass(); line.graphics.lineBitmapStyle(bitmap.bitmapData); line.graphics.moveTo(transformedLocation1.x, transformedLocation1.y); line.graphics.lineTo(transformedLocation2.x, transformedLocation2.y); addChild(line); }
How it works...
ActionScript's Graphic
class offers a rich set of drawing primitives. This allows you to create virtually any vector graphic you like. Some of the concepts will feel natural, while others can take a while to properly grasp. It's worth learning the ins and outs of the Graphics
class because a well-placed gradient or bitmap can really spice up any graph.
As in all other drawing methods we've seen in this chapter, first the coordinates are transformed.
When drawing a bitmap point, the embedded resource class is instantiated into a Bitmap
class. This is the class that will display the image.
Next we use some simple math to place the bitmap at the center of the coordinates. In ActionScript, the bitmap's (x , y) coordinates reflect the upper-left corner. So if we want to place the center of the bitmap at our coordinates, we need to subtract half of the width and height.
As usual, the final step is adding the bitmap to the graph sprite.
Drawing gradients requires extra work. To draw an area that is filled with a gradient, we use the beginGradientFill
method. It takes the following parameters:
- The type of gradient,
GradientType.LINEAR
andGradientType.RADIAL
are supported. - An array of colors through which the gradient will change. You can have up to 15 colors.
- The alpha values corresponding to the different colors in the previous array.
- The ratios where the full color will apply. The maximum range is [0, 255]. In this case we add a little more of the orange color. See the ActionScript reference for a visual explanation, available at: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html#beginGradientFill%28%29.
Optionally, you can also add a matrix that transforms the gradient. This will allow you to correctly place the gradient. In the case of this example, we stretch the gradient over the full screen and rotate it by 90 degrees.
When drawing bitmap fills for lines, there are a few points worth noting:
- Line bitmaps and gradients are applied to the actual drawn line. This means you need both the
lineStyle
andlineBitmapStyle
methods. You can't take out the first one or you would not see anything drawn. - The
lineBitmapStyle
method takes aBitmapData
class as an argument. The difference between this and theBitmap
class, is that bitmap is the actual representation on the screen, whileBitmapData
is just the bits that are needed to draw the bitmap. HenceBitmapData
does not have an x or y coordinate.
If you want to change the exact placement of the bitmaps, the lineBitmapStyle
method takes an optional Matrix
as an argument. This works similar to all the other matrix operations we've seen. Getting this exactly right isn't easy, so you may need to do some experimentation.
There's more...
We've only covered the very tip of the iceberg that is the Graphics
class.
As with most visual elements in ActionScript, bitmaps and gradients can be translated, rotated, made translucent, and much more. It's worth experimenting a little to get to know what's possible.
See also
Most ActionScript books have good coverage of the Graphics
class. But there are also a few that go into much more detail.
Although it can be a bit hard to get into, the live docs also provide a fairly in-depth overview of the features. This is available at: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html .