ActionScript Graphing Cookbook
上QQ阅读APP看书,第一时间看更新

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...

  1. 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's var 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 the Graph 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);
    }
  2. 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);
    }
  3. 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:

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 and lineBitmapStyle methods. You can't take out the first one or you would not see anything drawn.
  • The lineBitmapStyle method takes a BitmapData class as an argument. The difference between this and the Bitmap class, is that bitmap is the actual representation on the screen, while BitmapData is just the bits that are needed to draw the bitmap. Hence BitmapData 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.

Transformation

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.

Gradient lines and points, bitmap areas

We've only shown three examples. However you can combine any style with any type of graph. Feel free to extend the existing Graph class with whatever you need for your graphs.

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 .