Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
ActionScript Graphing Cookbook
ActionScript Graphing Cookbook

ActionScript Graphing Cookbook: Learn how to create appealing and interactive visual presentations of your data in ActionScript with this book and ebook.

eBook
$26.09 $28.99
Paperback
$48.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with Print?

Product feature icon Instant access to your digital copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Redeem a companion digital copy on all Print orders
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

ActionScript Graphing Cookbook

Chapter 1. Getting Started with Graph Drawing

In this chapter, we will cover:

  • Drawing in two dimensions

  • Building point charts

  • Creating a line graph based on a function

  • Adding labels and axes

  • Graphing a spreadsheet

  • Area charts

  • Multiple area charts

  • Styling a graph

  • Adding legends

  • Using Flex for charts

Introduction


In this chapter, we will see a number of recipes that go into the very basics of drawing in ActionScript. The recipes will explain the coordinate system, so that you know where you are drawing. A quick overview of the ActionScript DisplayList object and other ActionScript drawing functions is given.

A final recipe shows how Flex can be used to generate many standard graphs with virtually no actual programming. Flex is not the focus of the recipes, but the book wouldn't be complete without at least some coverage of the framework and its functions related to graph drawing.

Although we do not expect you to be an ActionScript expert, some basic knowledge will help you in quickly understanding and applying the recipes presented. Also, we will not go into the details of the tools used.

Drawing in two dimensions


This recipe goes into the very basics of what it takes to draw in two dimensions. There's a little math in there to explain the coordinate system and transformations. It's not the most interesting read, but it is very important that you understand this for all the following recipes.

We also extensively use the ActionScript 3.0 display list concept. We will explain the principles, but if you've never heard of it, you may want to read up on it in other ActionScript tutorials or books. A few of these are mentioned in the See also section of this recipe.

Getting ready

All recipes in this book are completely editor-agnostic; you can use them in any ActionScript editor you like. The samples are provided for the free FlashDevelop IDE available at http://www.flashdevelop.org/ , because it is completely free and of a very high quality.

If you want to follow along with FlashDevelop, now is the time to download and install it. Make sure you also configure the Flex SDK, if FlashDevelop does not do this for you. The Flex SDK is the part that will be responsible for compiling and executing your programs. More information can be found on the FlashDevelop wiki found at http://www.flashdevelop.org/wikidocs/index.php?title=Configuration#Configuring_the_Flex_SDK.

In FlashDevelop, create a new AS3 project. You can create one for each chapter, or re-use the same one for most of the recipes. Most recipes will require you to set the document class. This is done by right-clicking on the class in the project view and picking set document class from the options.

If you are using Flash Professional, we will not use the timeline that you may be used to. Information on setting up the document class can be found in the following blog article: http://active.tutsplus.com/tutorials/actionscript/quick-tip-how-to-use-a-document-class-in-flash/.

How to do it...

The first three steps will need to be performed for virtually all the recipes in this book, so we won't repeat them, unless they differ:

  1. Create a new class (in this case it's called Recipe1).

  2. Have it extend flash.display.Sprite.

  3. Set it as the Document Class.

    You should have the following piece of code:

    package  
    {
      import flash.display.Sprite;
      public class Recipe1 extends Sprite
      {
        public function Recipe1()
        {
        }
      }
    }

    Tip

    Downloading the example code

    You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

  4. Now run the code. You should get a blank screen with no warnings or errors.

  5. In order to draw a nice looking point, we will actually draw a small circle. The following piece of code creates a shape, draws a circle, moves the center point, and displays it:

    package  
    {
      import flash.display.Shape;
      import flash.display.Sprite;
    
      public class Recipe1 extends Sprite 
      {
        public function Recipe1() 
        {
                var point:Shape = new Shape( ); 
                point.graphics.beginFill( 0xff9933 , 1 );
                point.graphics.drawCircle( 0 , 0 , 3 );
                point.x = 20;                                 
                point.y = 20;
                addChild( point ); 
        }
      }
    }
  6. To more easily draw points inside graph coordinates of our choosing, we can introduce graph:Sprite, which will perform a transformation on all points we draw inside it:

    package  
    {
      import flash.display.Shape;
      import flash.display.Sprite;
      import flash.geom.Matrix;
    
      public class Recipe1 extends Sprite 
      {
        public function Recipe1() 
        {
          var graph:Sprite = new Sprite();
          graph.x = 20;
          graph.y = 20;
          addChild(graph);
    
          var point:Shape = new Shape(); 
          point.graphics.beginFill( 0xff9933 , 1 );
          point.graphics.drawCircle( 0 , 0 , 3 );
          point.x = 0;
          point.y = 0;
          graph.addChild(point);
        }
      }
    }

    The visual result is exactly the same as the previous piece of code, but now the point is at the coordinates (0,0).

  7. To obtain the transformation presented in the How it works... section of this recipe, we just need to apply the right transformation to the graph sprite:

    package  
    {
      import flash.display.Shape;
      import flash.display.Sprite;
      import flash.geom.Matrix;
    
      public class Recipe1 extends Sprite 
      {
        public function Recipe1() 
        {
          var graph:Sprite = new Sprite();
          graph.x = 400;
          graph.y = 300;
          graph.scaleY = -1;
          addChild(graph);
    
          var point:Shape = new Shape(); 
          point.graphics.beginFill( 0xff9933 , 1 );
          point.graphics.drawCircle( 0 , 0 , 3 );
          point.x = 0;
          point.y = 0;
          graph.addChild(point);
        }
      }
    }

How it works...

ActionScript 3.0 uses a concept called a display list. A display list is a collection of visual elements. The most important display list is your main class. This is the list that will be displayed (that is the reason why it extends Sprite).

This list is organized as a tree. It has a root node, to which various display objects are attached. Some of these display objects can also contain more display objects, hence the tree structure.

For instance, if you add a Sprite child to your main class, it will be displayed. If you add yet another Sprite child to that child, it too will be drawn on the screen.

However this isn't the end of the story. You can apply transformations to objects in the display list. A transformation can be scaling, rotating, and moving, or all at once. If you apply a transformation to one object, this transformation will also apply to all its children. This is how we displayed a point at (0,0) that was in the center of the screen.

When drawing a point, we do this by adding a shape to the display list:

  1. First a shape is created, which will hold all data related to our point (location, color, size).

  2. The ActionScript Graphics class is used to draw a solid circle into the shape.

  3. Next we change the location of the shape.

    Note

    We could also draw the circle at the position, but because the (0,0) coordinates of the circle sprite are at the top-left corner, this would not place the point in the center of the shape. This will complicate any transformation on the shape as we'll see later on. That's because the pivot point for scaling and rotating is the (0,0) coordinate.

  4. Finally we add the point object to the display list. Without this last line, the point would not be visible.

To understand the transformation that takes place, you should take note of two different coordinate systems that are used:

  1. Screen coordinates: If you used the default FlashDevelop settings, you will have a screen that goes from x = 0, y = 0 in the upper-left corner to x = 800, y = 600 in the bottom-right corner.

    This means that the X-axis of the coordinate system goes from the left of the screen to the right. The Y-axis goes from the top, down to the bottom.

    Usually the coordinates are given as a pair, so x = 0, y = 0 is written as (0,0). The following diagram demonstrates the screen coordinates:

  2. Most graphs however are not drawn in screen coordinates. For instance, if you want to plot a function, you may want to put the (0,0) coordinates in the center of the screen. This might look something like the following screenshot. The graph coordinates are in blue; we show only the direction and origin for the graph axes:

    So if you want to draw a graph point at (0,0), you would in effect have to draw it on the screen coordinates (400,300).

    To create such a transformation, we first translate the (0,0) point to the center of the screen. And second, the Y-axis is scaled by -1. This inverts the Y direction (up is down, and down is up).

In the next recipe, we will see a transformation matrix. This matrix is a mathematical shorthand notation for a coordinate transformation.

There's more...

Although this recipe seems simple; there's much you can learn from it. Let's look at some more features.

Graphics drawing

We've only covered the very basics of drawing with the Graphics class. Further recipes will show more details. But if you can't wait, try experimenting with the color and the size. The ActionScript 3.0 reference pages have the information you need: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html.

Coordinate systems and transformations

A great exercise is to experiment with the transformations. Try to obtain various results. If you modify the scaleX and scaleY variables, you can zoom in or out of the graph. You can even rotate your system.

Or if you're into maths, you can directly manipulate the transformation matrix of the graph sprite. Again, the ActionScript 3.0 reference guide will help you out: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html.

See also

If you want to read up on the display list, most of the ActionScript 3.0 fundamental books have a dedicated chapter about it. For instance, Learning ActionScript 3 or Essential ActionScript 3 (both published by O'Reilly) are good references.

If you want to read up on coordinate systems and transformations, you can find the best coverage in any vector maths book. Wikipedia is also a very informative source: http://en.wikipedia.org/wiki/Coordinate_system .

Building point charts


This recipe builds on the previous one. The previous recipe placed all the codes into one big method. This is fine for the first experiment, but when things get more complicated, you'll lose track of what goes where.

This recipe brings structure into the code and shows how to graph multiple points without repeating yourself.

Getting ready

Make sure you at least glanced over the previous recipe. You'll need it here.

Create a new, blank Recipe2 class, set it as the document class, and copy and paste the code inside the Recipe1 constructor placed inside it. To be sure, run the class and verify that everything looks the same as in the previous recipe.

How to do it...

We will tackle the generalization of the code in a few steps. If you take a look at the code, you'll notice that there are actually two important blocks: one that creates the graph shape and one that draws a point.

  1. In the first step we will extract these blocks into two methods:

    package  
    {
      import flash.display.Shape;
      import flash.display.Sprite;
      public class Recipe2 extends Sprite
      {
        private var graph:Sprite;
        
        public function Recipe2() 
        {
          createGraph();
          drawPoint();
        }
    
        private function createGraph():void
        {
          graph = new Sprite();
          graph.x = 400;
          graph.y = 300;
          graph.scaleY = -1;
          addChild(graph);
        }
    
        private function drawPoint():void
        {
          var point:Shape = new Shape(); 
          point.graphics.beginFill( 0xff9933 , 1 );
          point.graphics.drawCircle( 0 , 0 , 3 );
          point.x = 0;
          point.y = 0;
          graph.addChild(point);
        }
      }
    
    }

    The end result should still be exactly the same.

  2. The coordinates of the current graph are chosen for this one example; it would be much better to parameterize this. As parameters, we'll include the top-left and bottom-right coordinates we'd like to have:

    createGraph(-400, 300, 400, -300);

    Note

    See the images of the Drawing in two dimensions recipe in this chapter for the coordinate system that we are using.

    To make sure the method works with all possible choices of coordinates, we need to do some calculations in the createGraph method:

    • Translating the graph to the new center point (keeping in mind the scale).

    • Scale the graph to the right size. This can be done by comparing the current width and height against the values we want. The current width and height are fixed when you enter your project properties. But you can also obtain them from the stage object.

    • Lastly, if the coordinates are reversed, we must mirror the image.

    All these calculations together form this reusable method:

    private function createGraph(left:Number, top:Number, right:Number, bottom:int):void
        {
          var width:Number = Math.abs(right - left);
          var height:Number = Math.abs(bottom - top);
          var scaleWidth:Number = stage.stageWidth / width;
          var scaleHeight:Number = stage.stageHeight / height;
          var flipX:Boolean = (left > right);
          var flipY:Boolean = (top > bottom);
    
          graph = new Sprite();
          graph.x = scaleWidth * Math.abs(left);
          graph.y = scaleHeight * Math.abs(top);
          graph.scaleX = (flipX ? -1 : 1) * scaleWidth;
          graph.scaleY = (flipY ? -1 : 1) * scaleHeight;
          addChild(graph);
      }
  3. Now that we've got the hard part out of the way, let's make the drawPoint method a little more reusable. For now, we want to set all the points to the same style and size, so the only parameters to the method are the location.

    The resulting code is as follows:

    package  
    {
      import flash.display.Shape;
      import flash.display.Sprite;
    
      public class Recipe2 extends Sprite
      {
        private var graph:Sprite;
        public function Recipe2() 
        {
          createGraph(-400, 300, 400, -300);
          drawPoint(0, 0);
          drawPoint(20, 20);
          drawPoint(-40,-40);
        }
    
        private function createGraph(
    left:Number, top:Number, right:Number, bottom:Number):void
        {
          var width:Number = Math.abs(right - left);
          var height:Number = Math.abs(bottom - top);
          var scaleWidth:Number = stage.stageWidth / width;
          var scaleHeight:Number = stage.stageHeight / height;
          var flipX:Boolean = (left > right);
          var flipY:Boolean = (top > bottom);
    
          graph = new Sprite();
          graph.x = scaleWidth * Math.abs(left);
          graph.y = scaleHeight * Math.abs(top);
          graph.scaleX = (flipX ? -1 : 1) * scaleWidth;
          graph.scaleY = (flipY ? -1 : 1) * scaleHeight;
          addChild(graph);
        }
    
        private function drawPoint(x:Number, y:Number):void
        {
          var point:Shape = new Shape(); 
          point.graphics.beginFill( 0xff9933 , 1 );
          point.graphics.drawCircle( 0 , 0 , 3 );
          point.x = x;
          point.y = y;
          graph.addChild(point);
        }
      }
    }

    This code also shows that the method can be reused to draw several different points. If everything went well, you should see three points along a diagonal, with the bottom-left point being a little farther away from the others.

How it works...

To see how the transformation actually works, add the following line to the end of the graph constructor:

trace(graph.transform.matrix);

Note

If you have issues viewing the trace statements output, it may be due to the Flash player you are using or the FlashDevelop configuration. The FlashDevelop wiki has troubleshooting instructions right here: http://www.flashdevelop.org/wikidocs/index.php?title=AS3:Debugging.

This trace statement will display the transformation matrix in use. If you still remember your math, you may find this other way of looking at the process enlightening (see http://en.wikipedia.org/wiki/Transformation_matrix for an in-depth discussion on the topic).

The createGraph method sets up the following transformations:

  • It calculates the required scaling based on the target width and height.

  • The flipX and flipY variables are used to calculate whether the target coordinate system is mirrored or not. For instance, in this example, the Y- axis of the screen coordinates points down (0 is at the top and positive numbers are at the bottom), while the coordinate system in which we draw the graph works the other way around. This means we need to mirror the Y coordinates.

The drawPoint method draws a new point and can be called repeatedly to draw multiple points.

It creates a new shape for every point. This is not strictly necessary and might even cause a degraded performance when drawing many points. In the coming chapters, we'll see some uses for this approach, but if you have issues with performance, you can directly draw on the Recipe2 sprite and not instantiate new shapes for every point.

There's more...

Again, this basic program is very powerful. And with a few changes, it allows for lots of experimentation.

Coordinate system

Try to change the parameters of the createGraph method and see if you can predict the results.

Typically, scientific graphs will have their origin (0,0) in the center of the graph. Most business-type charts will have their origin somewhere in the bottom-left corner. All of these can be easily achieved by changing the parameters of the drawGraph method.

Scaling woes

If you change the coordinate system, you may notice that the point scales with the coordinate system. You can fix this by scaling back the point to the original size. Or you can transform all the operations, instead of the shape (refer to the next recipe for the solution).

Adding more parameters

If you like multiple points with different colors, then why not add another parameter to the drawPoint method.

See also

This recipe closely relates to many of the others in this chapter. So if something isn't clear, go back to the previous one, or skip ahead and come back to it later.

Creating a line graph based on a function


Now that we have our coordinate system and we know how to draw points, it's time to look a little further. This recipe introduces some other Graphics functions that will allow you to draw lines.

This recipe uses one of the most typical line graphs, namely the display of a function.

Getting ready

Before starting this recipe, we will go through one final iteration of our code in order to have a proper object-oriented structure that we can easily and quickly extend in this and later recipes.

Start by creating a Recipe3 class, set it as document class, and have it extend Sprite.

Next create a Graph class (in a new file, with name Graph.as) where we will centralize all graph drawing methods:

package  
{
  import flash.display.Shape;
  import flash.display.Sprite;
  import flash.events.Event;

  public class Graph extends Sprite
  {
    private var left:Number;
    private var top:Number;
    private var right:Number;
    private var bottom:Number;

    private var matrix:Matrix;

    public function Graph(left:Number, top:Number, right:Number, bottom:Number) 
    {
      this.left   = left;
      this.top    = top;
      this.right  = right;
      this.bottom = bottom;

      addEventListener(Event.ADDED_TO_STAGE, createGraph);
    }
    
    private function createGraph(event:Event):void
    {
      removeEventListener(Event.ADDED_TO_STAGE, createGraph);
      
      var width:Number = Math.abs(right - left);
      var height:Number = Math.abs(bottom - top);
      var scaleWidth:Number = stage.stageWidth / width;
      var scaleHeight:Number = stage.stageHeight / height;
      var flipX:Boolean = (left > right);
      var flipY:Boolean = (top > bottom);

      matrix = new Matrix(
        (flipX ? -1 : 1) * scaleWidth,
        0,
        0,
        (flipY ? -1 : 1) * scaleHeight,
        scaleWidth * Math.abs(left),
        scaleHeight * Math.abs(top)
      );
    }

    public function drawPoint(x:Number, y:Number):void
    {
      var transformedLocation:Point = matrix.transformPoint(new Point(x, y));
      var point:Shape = new Shape(); 
            point.graphics.beginFill( 0xff9933 , 1 );
            point.graphics.drawCircle( 0 , 0 , 3 );
      point.x = transformedLocation.x;
      point.y = transformedLocation.y;
            addChild(point);
    }
  }
}

You'll notice two major changes from the previous recipe:

  1. Due to the way the display list works, we don't have access to the stage until the graph is attached to it. This means we have to create the graph after the ADDED_TO_STAGE event is fired. This detail is not important for the rest of the recipe, so if you don't understand it at this point, don't worry.

  2. Instead of transforming the graph shape (via its x, y, scaleX, and scaleY parameters), we transform the coordinates of the point. The result is that the circle is always as we expected and is not scaled with your coordinates system (see the Scaling woes section in the previous recipe).

How to do it...

  1. We now start with the same program as the Building point charts recipe, but using the new Graph class:

    package  
    {
      import flash.display.Sprite;
    
      public class Recipe3 extends Sprite
      {
        private var graph:Graph;
    
        public function Recipe3() 
        {
          graph = new Graph( -400, 300, 400, -300);
          addChild(graph);
    
          graph.drawPoint(0, 0);
          graph.drawPoint(20, 20);
          graph.drawPoint(-40,-40);
        }
    
      }
    }

    If everything went right, you should see, once again, the exact same result. Only now, our main program (Recipe3) only shows what we want to do (that is, to create a graph and draw points). How those actions are performed, is written inside the Graph class.

  2. Now to create this recipe. We need a way to draw lines. Add the following method to the Graph class:

    public function drawLine(x1:Number, y1:Number, x2:Number, y2:Number):void
    {
      var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y1));
      var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y2));
    
      graphics.lineStyle(2, 0x000000);
      graphics.moveTo(transformedLocation1.x, transformedLocation1.y);
      graphics.lineTo(transformedLocation2.x, transformedLocation2.y);
    }
  3. Now let's do something useful with this. Say you want to draw the sine function in the range starting from –π/2 and ending at π/2. The result will go from -1 to 1. So we use (-π/2, 1) and (π/2) as the upper-left and lower-right corners of our graph.

    But a sine is not a linear function, so we can't just draw one line from (–π/2, -1) to (π/2, 1). What we will do, is approximate the sine curve by splitting it into smaller parts and drawing a number of shorter lines.

    Take a look at the following code:

    package  
    {
      import flash.display.Sprite;
      import flash.geom.Point;
    
      public class Recipe3 extends Sprite
      {
        private var graph:Graph;
    
        public function Recipe3() 
       {
          graph = new Graph( -Math.PI/2, 1, Math.PI/2, -1);
          addChild(graph);
    
          var i:Number = -Math.PI/2;
          var step:Number = 0.1;
          var previousPoint:Point = new Point(i, Math.sin(i));
          for (i += step; i <= Math.PI/2; i += step)
          {
            var point:Point = new Point(i, Math.sin(i));
            graph.drawLine(previousPoint.x, previousPoint.y , point.x, point.y);
            previousPoint = point;
          }
        }
    
      }
    }

    The result is the sine curve, as shown in the following screenshot:

    Because we used many small lines (the program uses π / 0.1 or 31 pieces), the segments are hardly distinguishable.

  4. Change the step variable to 1 and you'll immediately see the separate lines, as shown in the following screenshot:

    You can still see the sine curve, but it's clear that the three segments don't have a very good approximation.

How it works...

To draw a line, we use the Graphics methods as follows:

  • We calculate the correct position of the beginning and the end points of the line

  • The ActionScript Graphics methods are used to set a line style and draw the line

You can try this out with any data, not just a function. Replace the drawPoint method calls in Recipe3 with the following piece of code:

      graph.drawLine(0, 0, 20, 40);

You should see a short line appear. Once we can draw a line, drawing a function just builds on top of that:

  • To change the way the transformation is handled, instead of scaling the entire shape, we just scale the coordinates. The result is that the graphics element, such as circles and line widths, don't scale with the coordinate system.

  • To approximate the actual sine curve, we take samples and fill in the holes with a straight line. This is linear interpolation and if it's done right, it's hardly distinguishable from the real thing.

There's more...

If function drawing is the main aim of your program, there are quite a few ways this code can be extended and improved.

Improving the Graph class

Until now, our two graph methods (drawPoint and drawLine) have taken number arguments. A better interface would probably have point classes as arguments. Why not try this refactoring yourself? It will give you more insight into the code. The result will be used in the next recipes.

Using points to draw functions

There are many ways to draw a function. One thing you may have thought about using is the drawPoint method, just placing many points. You can quite easily adapt the program to do this. However, you'll notice you need quite a lot more points to obtain the same result.

Curves

The ActionScript Graphics class can also draw so called Bézier curves with the curveTo method. You'll only need two well-chosen curves to get a very convincing result. This is not for the faint of heart, but you can find code that should get you started at these sites:

http://www.cartogrammar.com/blog/actionscript-curves-update/

http://gskinner.com/blog/archives/2008/05/drawing_curved_.html

See also

If you want to read up on linear interpolation, a good starting point is Wikipedia http://en.wikipedia.org/wiki/Linear_interpolation or your old, math books.

The sine function is also well explained on Wikipedia:

http://en.wikipedia.org/wiki/Sine.

Adding labels and axes


Before diving into some more graph types, it's about time we started adding axes and scales. If we don't have those, there really is no way to properly interpret our nice charts.

In this recipe we will add a horizontal and vertical axis to the sine graph we created in the previous recipe. We will also add markers and labels.

Getting ready

This recipe continues to expand the Graph class presented in the previous recipe. So if you haven't written that yet, copy it from the provided sources.

Next, create a Recipe4 class, just as we did in the previous recipes.

How to do it...

To create axes, we will add two methods to the Graph class. They are as follows:

  • public function drawVerticalAxis(x:Number, y1:Number, y2:Number)

  • public function drawHorizontalAxis(y: Number, x1:Number, x2:Number)

Calling the methods will draw a straight line from (x,y1) to (x,y2) and (x1,y) to (x2,y), respectively.

  1. For our first implementation we can simply reuse the drawLine method.

    Add the following methods to the Graph class:

        public function drawVerticalAxis(x:Number, y1:Number, y2:Number)
        {
          drawLine(x, y1, x, y2);
        }
    
        public function drawHorizontalAxis(y: Number, x1:Number, x2:Number)
        {
          drawLine(x1, y, x2, y);
        }
  2. Now you can try them out in the Recipe4 class:

    package  
    {
      import flash.display.Sprite;
      import flash.geom.Point;
    
      public class Recipe4 extends Sprite
      {
        private var graph:Graph;
    
        public function Recipe4() 
        {
          graph = new Graph( -Math.PI/2, 1, Math.PI/2, -1);
          addChild(graph);
    
          graph.drawVerticalAxis(0, 1, -1);
          graph.drawHorizontalAxis(0, -Math.PI / 2, Math.PI /2);
    
          var i:Number = -Math.PI/2;
          var step:Number = 0.1;
          var previousPoint:Point = new Point(i,Math.sin(i));
          for (i += step; i <= Math.PI/2; i += step)
          {
            var point:Point = new Point(i, Math.sin(i));
            graph.drawLine(previousPoint.x, previousPoint.y ,point.x, point.y);
            previousPoint = point;
          }
        }
    
      }
    }

    The result should be the same graph as before, but now with two lines forming an axis.

    A typical axis has at least two features that make it actually useful:

    i. Regularly spaced tick marks.

    ii. Labels associated with those marks.

  3. We will first draw the marks. In order to do this, we first create a separate drawAxisLine method. This will also allow you to style the axes differently than the actual graph.

    A first revision of the drawHorizontalAxis method looks like the following code:

    public function drawHorizontalAxis(y: Number, x1:Number, x2:Number):void
    {
      var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y));
      var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y));
      drawAxisLine(transformedLocation1, transformedLocation2);
    }
    
    private function drawAxisLine(p1: Point, p2: Point):void
    {
      var line:Shape = new Shape();
      line.graphics.lineStyle(1, 0x000000);
      line.graphics.moveTo(p1.x, p1.y);
      line.graphics.lineTo(p2.x, p2.y);
      addChild(line);
    }
  4. Now we add marks. This uses a stepping algorithm very similar to the one we used for drawing a function. First we calculate the mark position on the axis and next a short line is drawn, perpendicular to the axis:

    public function drawHorizontalAxis(y: Number, x1:Number, x2:Number):void
    {
      var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y));
      var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y));
      drawAxisLine(transformedLocation1, transformedLocation2);
    
      var step:Number    = 50;
      for (var markX:Number = transformedLocation1.x; 
        markX <= transformedLocation2.x; 
        markX += step) 
      {
        var markPoint1:Point = new Point(markX, transformedLocation1.y);
        var markPoint2:Point = new Point(markX, transformedLocation1.y + 10);
        drawAxisLine(markPoint1, markPoint2);
    }
    }
  5. And finally we add labels. To display a label we use the ActionScript TextField class. This class has a tremendous amount of parameters that allow you to customize how the text is displayed. We will look at a few parameters in the later recipes, but for now, we use the standard formatting.

    We don't want to clutter the display too much, so we only add a text label every four markers:

    public function drawHorizontalAxis(y: Number, x1:Number, x2:Number):void
    {
      var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y));
      var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y));
      drawAxisLine(transformedLocation1, transformedLocation2);
    
      var labels:Array   = ["-PI/2","-PI/4","0","PI/4","PI/2"];
      var step:Number = 50;
      var labelCount:int = 0;
      for (var markX:Number = transformedLocation1.x; 
        markX <= transformedLocation2.x; 
        markX += step) 
      {
        var markPoint1:Point = new Point(markX, transformedLocation1.y);
        var markPoint2:Point = new Point(markX, transformedLocation1.y + 10);
        drawAxisLine(markPoint1, markPoint2);
    
        if (int(markX) % 200 == 0)
        {
          //place a label every 4 markers
          var textField:TextField = new TextField();
          textField.text = labels[labelCount++];
          textField.x = markX;
          textField.y = transformedLocation1.y + 12;
          addChild(textField);
        }
      }
    }
  6. Run the program again, and you'll see a horizontal axis with values.

How it works...

This recipe is probably one of the least spectacular ones. It just builds on top of ActionScript methods for drawing lines and displaying text. There's a lot of mechanical work involved in getting everything in the right location, but nothing complicated.

The best way to understand the recipe is to play with the various parameters:

  • Increase and decrease the marker step size

  • Change the size of the markers

  • Change the number of labels (make sure you have enough label values in the labels array; if not, you'll end up receiving error messages)

There's more...

Now let's talk about some other options, or possibly some pieces of general information that are relevant to this task.

Vertical axis

Only the code for the horizontal axis was shown. The code for the vertical axis is, of course, very similar and a great exercise.

Screen versus graph coordinates

All the axes drawing code was written in screen coordinates. This simplified a few things, but it could also make it more complex to correctly place the marks. A good exercise is to rewrite the code using graph coordinates.

Error checking and adding parameters

We haven't really bothered ourselves with adding error checking to the parameters (what if the first value of the axis coordinate is larger than the second?). We also haven't yet made the code more generic. You can add parameters for the number of marks you want to be shown on the labels.

Graphing a spreadsheet


Graphing functions is nice, but visualizing a spreadsheet is probably the most popular use case for graphs. Having a visual representation of tabular data can result into insights previously hidden behind the numbers.

In this recipe, we will structure the code to use data from a fixed array in the ActionScript program. In the next chapter, we'll go into all kinds of ways to get the data into that array.

Getting ready

Create a new document class called Recipe5 and have it extend Sprite. Also make sure to copy the updated Graph class from the provided source package. It has enhanced and more flexible axes methods (if you implemented any of the items mentioned in the There's more... section of the Adding labels and axes recipe in this chapter, you may have already created a very similar one).

This time we'll focus on only positive numeric data, so we'll put the origin (0,0) of the graph in the bottom-left corner:

package  
{
  import flash.display.Sprite;

    private const MAX_X:int  = 700;
    private const MAX_Y:int  = 500;
    private const BORDER:int = 50;
    private const TICK:int   = 50;

  public class Recipe5 extends Sprite 
  {
    private var graph:Graph;

    public function Recipe5() 
    {
      graph = new Graph( -BORDER, MAX_Y + BORDER, MAX_X + BORDER, -BORDER);
      addChild(graph);
      graph.drawHorizontalAxis(0, 0, MAX_X, TICK, ["0", MAX_X]);
      graph.drawVerticalAxis(0, 0, MAX_Y, TICK, ["0", MAX_Y/2, MAX_Y]);
    }
  }
}

If you run this program, you should see both axes run from the bottom-left corner and there should be two labels on the horizontal axis and three on the vertical axis.

How to do it...

For now, we'll just show point charts. Feel free to convert this into a line chart (as shown in the Creating a line graph based on a function recipe in this chapter) and in later recipes you'll learn how to draw many different types of charts.

If we have the following table:

We want to draw two points: (10,40) and (20,60).

Storing data is easiest in a two dimensional array. In the next chapter, we'll go over many different ways of storing data (such as in files and on the Internet). The array mimics how you represent this data in a program such as MS Excel:

private var graph2d: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]];

All the points are grouped together. Each entry in the array is one (x , y) coordinate on the graph.

The code to draw this dataset is just a simple loop:

for (i = 0; i < graph2d.length; i++)
{
  graph.drawPoint(graph2d[i][0], graph2d[i][1], 0x3399ff);
}

This structure does have one problem: it's not easy to manipulate the data. You may want to change the data, for instance, if this was connected to live web statistics that are updated every minute (we'll see more on that in the next chapter). Say you want to change the point (150,150) to (150,200). How would you do that? You need to loop over the array and find the correct entry and change it.

However, searching this way in a large array can become slow quite quickly. If the array is always sorted, like in the preceding example, you could implement your own version of a search algorithm to make it quicker. But then you'd need to create your own insertion algorithm to make sure the data remains in order.

No matter how you solve this, if you need to manipulate the data a lot, this is not a good data structure.

See the There's more... section of this recipe for other solutions to these problems.

How it works...

The data we want to display is a simple data mapping from one value to the another. Imagine an Excel spreadsheet with two columns. One column holds the x-axis values while the other holds the y-axis value. Two numbers on the same row present one (x , y) point.

That is why a two-dimensional array is one of the best ways to represent data: it's an easy structure to program and it's easy to read. However, it is hard to manipulate. If you have a fixed data set, this is the structure you want.

There's more...

There are an endless number of possible ways to represent data. Depending on your data source or your specific data set, you may want to look into other options. In the following section, we present the two most popular ones, each with its own advantages and disadvantages. Ultimately, it is possible to combine most advantages into one structure, but it will require additional development.

Two arrays

The easiest solution to store data is in two arrays, one for each column in the spreadsheet:

private var graph1x:Array = 
[0, 50, 100, 150, 200, 250, 300, 350, 400, 
450, 500, 550, 600, 650, 700];
private var graph1y:Array = 
[20, 70, 0, 150, 300, 200, 400, 20, 60, 250, 90, 400, 500, 450, 320];

And you can draw the graph with a simple loop:

for (var i:int = 0; i < graph1x.length; i++)
{
  graph.drawPoint(graph1x[i], graph1y[i], 0xff9933);
}

This works effectively and is completely understandable. There is a major drawback to this approach that is already clear in this simple example.

There's no easy way to quickly verify that you have the same number of elements in both arrays. You can write a test in your code, but if you want to edit the data, it's hard to see which value belongs to which.

For instance, the 400 x-value maps to 60 on the y-axis. That isn't readily apparent from the code. If you forget to add a y-value, you run the risk of breaking your entire program.

Associative array

If inserting and updating data is important, you may want to look into a third solution: the object or associative array.

private var graphObject:Object = { 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 };

Although the notation looks similar to the previous one, the data structure that is created internally is quite different. Drawing it is a little more complicated and requires the usage of the for-in loop (again we shift the points to demonstrate the difference):

for (var s:String in graphObject)
{
  graph.drawPoint(Number(s) + 8, graphObject[s], 0xff3399);
}

Because the x coordinate is stored as an object property, it is stored as a string. Before we can draw it, we need to convert it back to a number.

This data structure is perfect for manipulation. Instead of having to search through it to find the item we want to change, we just write the following:

graphObject[150] = 200;

However, there is one very major disadvantage of the associate array and the for-in loop: you should not rely, in any way, on the order in which elements are looped over. So there's no guarantee that the loop will first draw (0,20) and then (50,70), and so on.

Order will become important if you want to draw more complicated charts than the point chart shown. In that case, you need to first convert the object to an array and then sort the array.

Vectors

If you like to work in a more object-oriented manner, and to avoid some of the pitfalls of arrays and increase performance, you may want to look into vectors.

Although the code that you need to write tends to be much more verbose than arrays and objects, they offer a very high level of type safety and have many convenience functions.

For instance, you can store points in the Point objects:

var point:Point = new Point(0,20);

And store these points in a point vector:

var graphVector:Vector.<Point> = new Vector.<Point>();
graphVector.push(point);

Associative array to two-dimensional array conversion

If you intend to manipulate your data inside your ActionScript program you will probably want to write at least a conversion function from the associate array to the ordered two-dimensional arrays. Potentially, you'll also need to do this the other way around.

What you need to do is:

  • Use a for-in loop to construct a two-dimensional array

  • Use the Array.sort method and the custom order function to sort the array

See also

If you're not confident with manipulating (associative) arrays, it's best to look at one of the ActionScript fundamentals books. Both data structures are vital to understanding most of the recipes in this book.

Area charts


In the previous recipes we've learned:

  • Transforming the data so that it shows up at the right location on the screen

  • Using the correct data structure so it's easy to display it

In the remaining recipes in this chapter, we will look into ActionScript's drawing methods and show you a few ways to customize the display.

This recipe looks at drawing area charts. They resemble a function chart, but the area between the chart line and the x-axis is filled. They are ideal to represent volumes.

Getting ready

Create a Recipe6 document class and set up the graph as in the previous recipe. We will use the two-dimensional data set because we will need an ordered data set:

package  
{
  import flash.display.Sprite;

  public class Recipe6 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 Recipe6() 
    {
      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"]);
    }

  }
}

How to do it...

  1. Add the following code to the Recipe6 constructor:

    for (var i:Number = 1; i < data.length; i++)
    {
      graph.drawLine(data[i-1][0], data[i-1][1], data[i][0], data[i][1]);
    }

    Running the program at this point will yield the data set from the previous recipe, but now connected with a line.

  2. In the Graph class, we create a copy of the drawLine method and name it drawArea. In the main program, we now replace the drawLine call. The result should still be the same. But now we change the code so that the area is filled:

    public function drawArea(x1:Number, y1:Number, x2:Number, y2:Number):void
    {
      var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y1));
      var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y2));
      var transformedOrigin:Point    = matrix.transformPoint(new Point(0, 0));
    
      var area:Shape = new Shape();
      area.graphics.beginFill(0xff9933);
      area.graphics.moveTo(transformedLocation1.x, transformedLocation1.y);
      area.graphics.lineTo(transformedLocation2.x, transformedLocation2.y);
      area.graphics.lineTo(transformedLocation2.x, transformedOrigin.y);
      area.graphics.lineTo(transformedLocation1.x, transformedOrigin.y);
      area.graphics.endFill();
      addChild(area);
    }

    If you run the program now, you should see an orange area chart. Everything below the line is now nicely filled with the orange color.

How it works...

This recipe is created in two steps: first, display a line chart and next, fill the void beneath the line to obtain an area.

Because drawing a line requires two points, we start counting at 1 instead of 0. In the loop, we draw a line between the previous point and the current one.

There are two other things to note from the code:

  • We calculate the transformed origin. Actually, we only need the 0 y-coordinate, but it's easier to just use the matrix for this calculation.

  • Instead of drawing a line between two points, we create a "fill" between four points: the two that were used for the line and the two on the x-axis (with y = 0).

There's more...

As with previous recipes, there's a lot that can be customized. Most of these will be discussed in some of the next recipes, but there's nothing keeping you from starting to experiment.

Having the color as a parameter

Right now, the fill color is fixed. You can make this a variable by using it as an argument to the drawArea method.

The fill style

If you check out the ActionScript documentation, you'll find that there are two more ways of creating fills: the beginGradientFill and beginBitmapFill methods. They are a bit more complicated, but can be used to obtain dramatic effects.

See also

The ActionScript 3.0 reference has a lot more detail on creating and drawing filled shapes. It can be found at the following URL:

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html

Multiple area charts


In this recipe, we're going to visualize multiple sets of data on one chart.

Getting ready

As usual, create a Recipe7 document class. We'll start with the code from the previous recipe. Only now, we've slightly changed the data set to demonstrate some of the items covered better. There's also an added set of data. We've chosen to store it in the same array for simplicity, but there are other ways of course.

The following is the starting class:

package  
{
  import flash.display.Sprite;

  public class Recipe7 extends Sprite
  {
    private var graph:Graph;
    private var data:Array = [[0, 20, 50], [50, 70, 40], [100, 0, 100], 
[150, 150, 150], [200, 300, 200], [250, 200, 170], 
[300, 170, 160], [350, 20, 120], [400, 60, 80], 
[450, 250, 150], [500, 90, 20], [550, 50, 40], 
[600, 110, 90], [650, 150, 150], [700, 320, 200]];

    public function Recipe7() 
    {
      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"]);

      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]);
      }

    }

  }

}

How to do it...

There are two ways to show multiple area charts. You can stack the charts on top of each other or you can make them transparent and have them overlaid.

We'll cover the transparent overlay first, because it's the easiest.

  1. Rewrite the drawArea method as follows:

    public function drawArea(x1:Number, y1:Number, x2:Number, y2:Number, 
    colour:uint = 0xff9933, alpha:Number = 1):void
    {
      var transformedLocation1:Point = matrix.transformPoint(new Point(x1, y1));
      var transformedLocation2:Point = matrix.transformPoint(new Point(x2, y2));
      var transformedOrigin:Point    = matrix.transformPoint(new Point(0, 0));
    
      var area:Shape = new Shape();
      area.graphics.beginFill(colour, alpha);
      area.graphics.moveTo(transformedLocation1.x, transformedLocation1.y);
      area.graphics.lineTo(transformedLocation2.x, transformedLocation2.y);
      area.graphics.lineTo(transformedLocation2.x, transformedOrigin.y);
      area.graphics.lineTo(transformedLocation1.x, transformedOrigin.y);
      area.graphics.endFill();
      addChild(area);
    }
  2. If we now rewrite the main loop, we can draw multiple area charts with transparency:

    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], 
    0xff9933, 0.5);
      graph.drawArea(data[i - 1][0], data[i - 1][2], data[i][0], data[i][2],
    0x3399ff, 0.5);
    }

    Creating stacked charts is a little more complicated. Once again, we start by expanding the drawArea method. We add two more parameters that define the bottom y-coordinates of the area. In the previous graphs, they've always been zero, so we leave that in as the default:

    public function drawArea(x1:Number, y1:Number, x2:Number, y2:Number, 
    colour:uint = 0xff9933, alpha:Number = 1, 
    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();
      area.graphics.beginFill(colour, alpha);
      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);
    }

    Use the following code:

    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.drawArea(data[i - 1][0], data[i - 1][1] + data[i - 1][2], 
       data[i][0], data[i][1] + data[i][2], 
       0x3399ff, 1,
               data[i - 1][1], data[i][1]);
    }

How it works...

Areas are drawn by moving from one point to the other, either clockwise or counter-clockwise. We rushed over this important point in the previous recipe, but it is important in this one.

Because the areas are a little more complex, you need to be extra careful to get the order right. Otherwise you'll run into some strange phenomena.

When overlaying multiple charts, we use the alpha property of the fills. The alpha value controls the transparency of the fill. By making the fill translucent, we can see both areas behind each other.

When stacking multiple charts, we need to use the sum of both coordinates to properly place the different data sets. The bottom coordinates of the second data set are given by the first area chart, while the top coordinates are the sum of two data sets.

There's more...

We've seen the basics of drawing multiple data sets on one chart. In later chapters, there will be many more ways of displaying this information. In the meantime, here are a few ways to expand this recipe.

Improving the interface

The drawArea method's parameters can be improved upon. In particular if you want to draw a third or fourth set of data points, this is going to become unwieldy.

One option is to accept arrays of y-coordinates.

Styling the fill

As with the previous recipe, there are many options to style the fill. We'll look into a few in the next recipe.

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 .

Adding legends


Without a little explanation, any graph will quickly become incomprehensible. Especially when showing multiple sets of data, it is important to properly distinguish between the two. A legend can do just that.

Getting ready

For the Recipe9 class, we start from the overlapping multiple area charts class. So copy that class and rename it to Recipe9 to follow along.

How to do it...

  1. The legend related display methods will receive their own class. We start by creating a new Legend class that extends Sprite. Optionally, you can add a title:

    package  
    {
        import flash.display.Sprite;
        import flash.text.TextField;
        import flash.text.TextFieldAutoSize;
    
        public class Legend extends Sprite
        {
          private var lineHeight:Number = 20;
          private var lines:int = 0;
          
          public function Legend(title:String = null) 
          {
             if (title != null) {
                    var titleField:TextField = new TextField();
                    titleField.text = title;
                    titleField.autoSize = TextFieldAutoSize.LEFT;
                    addChild(titleField);
                    lines++;
                }
            }
            public function addKey(key:String, color:uint, alpha:Number):void
            {
                // see further
            }
      }
    }
  2. In the main program (Recipe9), you can add the legend to the display with the following code:

    var legend:Legend = new Legend("Legend title");
    legend.x = 600;
    legend.y = 20;
    legend.addKey("First series", 0xff9933, 0.5);
    legend.addKey("More data points", 0x3399ff, 0.5);
    addChild(legend);
  3. As you can see, we've already added methods to add the display of actual keys. In typical graph fashion, we want to show a small square containing the color of that data set with some text next to it to name the data set.

    The code isn't overly complicated and uses the drawRect method from the Graphics class and the plain TextField class we've seen before:

    public function addKey(key:String, color:uint, alpha:Number):void
    {
      var keySample:Shape = new Shape();
      keySample.graphics.lineStyle(1);
      keySample.graphics.beginFill(color, alpha);
      keySample.graphics.drawRect(0, lines * lineHeight, 15, 15);
      keySample.graphics.endFill();
      addChild(keySample);
    
      var keyField:TextField = new TextField();
      keyField.text = key;
      keyField.x = 20;
      keyField.y = lines * lineHeight;
      keyField.autoSize = TextFieldAutoSize.LEFT;
      addChild(keyField);
    
      lines++;
    }

    If you run the program now, you'll notice one thing still missing: a nice box around our legend to distinguish it from the actual graph.

  4. The only tricky thing is that it needs to be updated dynamically when a key is added. So we store it in an instance variable:

        private var box:Shape;
  5. Next we create the method to update the box:

         private function updateBox():void 
        {
          if (box != null) {
            removeChild(box);
          }
          box = new Shape();
          box.graphics.lineStyle(1);
          box.graphics.drawRect(-5, -5, width+6, height+6);
          addChild(box);
        }
  6. Now we should execute the updateBox method every time the legend changes. So the final step is to add it to the end of the constructor and the addKey methods.

How it works...

Just like with the Graph class, we use the Legend class to hold all of the separate graphical elements of the legend. That way we can just work from the (0,0) origin and not worry about the exact location where the legend will be placed.

Since this would require its own chapter, we won't be going into the details of styling and customizing the textField class. The only option that we use the autoSize property. It will make sure that the size of the text field fits the text and isn't just left at the default 100x100. This guarantees that the sprite's size will be exactly the size of the text and allows us to easily draw a nice fitting box around the entire legend display.

The line counter is responsible for making sure we can place each individual legend key at the right distance.

You may have noticed that we draw the legend in screen coordinates, not graph coordinates. In many cases, it's easier to place it in the correct location that way. Although if you want to fix the legend in relation to the graph (for instance, always in the bottom, at the center) you may want to think about putting it inside the Graph class and use the transformed coordinates. In that case, the Legend class would probably be a child of the Graph class.

The legend is a sprite, which means you can use the legend like any other one. You can resize it, move it, and even rotate it if you want (you may need to use embedded fonts on the text fields to perform some of those operations).

There's more...

With this recipe, we've only scratched the surface of what you can do with legends.

TextField customization

In this recipe, we've used the very basics of the textField class. However, the textField class is one of the most versatile ActionScript classes available. It offers so many options that ActionScript reference books need an entire chapter or two to cover it.

So if you want to change the text display, start with the live docs for textField and textFormat and go from there.

A background

In this recipe, we've kept the legend transparent. It is perfectly possible to add a background color to it. To obtain this, extends the updateBox method so it also draws a fill (see the previous recipe). One thing to keep in mind: you need to make sure that the box is drawn behind the keys and title and not on top.

Research the addChildAt method to find the solution for this issue: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObjectContainer.html#addChildAt%28%29.

See also

More information on customizing textField can be found in the Adobe live docs:

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextField.html.

The textFormat class is the main way to change fonts, sizes, and many more options:

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextFormat.html.

Using Flex for charts


No book on ActionScript graphing would be complete without at least mentioning Flex. The Flex software development kit also contains an extensive API for drawing different types of graphs.

The techniques we've discussed in the previous recipes are much more powerful, but depending on the case, a small Flex component might be enough.

Getting ready

Since we need access to the Flex library, we'll need to set up our FlashDevelop workspace differently. The easiest way is to create a new project. When asked for the type of project, pick Flex 3 project (instead of AS3 Project, which we use throughout the other parts of this book).

If you browse through the files in the src directory of your project, you will now find a Main.mxml file instead of the previous Main.as file. This is the file that describes your user interface. Instead of programmatically adding all the sprites and shapes to your interface, you will add them to this file.

How to do it...

  1. Open Main.mxml. All the code presented here should be added inside the mx:Application tags.

  2. First let's start with the data set definition:

      <mx:Script><![CDATA[
        import mx.collections.ArrayCollection;
        [Bindable]
        public var dataSet:ArrayCollection = new ArrayCollection([
          {x:0,   y1:20,  y2:50},
          {x:50,  y1:70,  y2:40},
          {x:100, y1:0,   y2:100},
          {x:150, y1:150, y2:150},
          {x:200, y1:300, y2:200},
          {x:250, y1:200, y2:170},
          {x:300, y1:170, y2:160},
          {x:350, y1:20,  y2:120},
          {x:400, y1:60,  y2:80},
          {x:450, y1:250, y2:150},
          {x:500, y1:90, y2:20},
          {x:550, y1:50, y2:40},
          {x:600, y1:110, y2:90},
          {x:650, y1:150, y2:150},
          {x:700, y1:320, y2:200}
        ]);
        ]]></mx:Script>
  3. This is the same set we used in previous recipes. Now we add the actual chart and legend:

      <mx:Panel title="Our first Flex chart">
        <mx:AreaChart id="areaChart" showDataTips="true" dataProvider="{dataSet}">
          <mx:horizontalAxis>
            <mx:CategoryAxis
              dataProvider="{dataSet}"
              categoryField="x"
            />
          </mx:horizontalAxis>
          <mx:series>
            <mx:AreaSeries 
              yField="y1" 
              displayName="First series">
              <mx:areaFill>
                <mx:SolidColor color="0xff9933" alpha="0.5" />
              </mx:areaFill>
            </mx:AreaSeries>
            <mx:AreaSeries 
              yField="y2" 
              displayName="More data points">
              <mx:areaFill>
                <mx:SolidColor color="0x3399ff" alpha="0.5" />
              </mx:areaFill>
            </mx:AreaSeries>
          </mx:series>
        </mx:AreaChart>
        <mx:Legend dataProvider="{areaChart}"/>
      </mx:Panel>

How it works...

Flex has a few new data structures; in this recipe we use the ArrayCollection data structure. This is a specially defined data structure that makes it easy to manage chart data. In fact, if you wanted to include the Flex library in your project, you could use the class for your own graph drawing.

Now let's look at the structure as a display list: the root element is a Panel class. This is a simple wrapper class to which you can add a title.

Inside this panel, there are two visual elements: an area chart and a legend. The legend is the easiest of the two explain; we use the default settings and let it read its data from the chart. It's all automatically added and filled.

The area chart is a little more involved:

  • The dataProvider attribute links this chart to the data we previously defined.

  • The showDataTips attribute is enabled to show you how quickly you can get some pretty fancy charts with Flex. If this is enabled, you can hover over the data points with your mouse, and you'll see a pop up with more details.

  • The horizontal axis is mapped to the x element inside the data set. Note that scaling of the axes happens automatically (but it can be overridden if required).

  • Finally we add two data series, both of which we map to the data set we defined previously. We also apply the same fill that was used in the previous recipes.

If you run the program, you will see a graph similar to the one presented in the multiple area charts recipe.

The difference is the way we defined the chart. With Flex you describe how the chart will look and let Flex do the work for you. In plain ActionScript, you have full control, but you have to do all the hard work.

The choice will depend on the application and most likely also on personal preferences.

There's more...

The Flex charting API is immense and with the recipe above, and we haven't even scratched the surface. If you think this style of development is for you, here are a few more things you can do.

Flex without MXML

If you like Flex, but don't like MXML, there's a way to program Flex with virtually no XML. Since Flex wasn't built for this purpose, you'll find fairly little documentation explaining this.

If this is something you want to try out, start with this StackOverflow question:

http://stackoverflow.com/questions/141288/possible-to-use-flex-framework-components-without-using-mxml.

ActionScript in Flex

Everything inside the mx:Script tags is pure ActionScript code. If you don't like the ArrayCollection data structure, you can always write your own bit of ActionScript that maps from any data structure to the one Flex expects.

See also

If you like to get into Flex, there are numerous books. Also, the online documentation is very complete. For charting, your best starting point is available here:

http://livedocs.adobe.com/flex/3/html/help.html?content=charts_intro_7.html.

Left arrow icon Right arrow icon

Key benefits

  • Learn how to create various visually dynamic graphs and charts
  • Import data from different sources, such as web services
  • Learn how to map geographical data, visualize in 3D

Description

"A picture is worth a thousand words" has never been more true than when representing large sets of data. Bar charts, heat maps, cartograms, and many more have become important tools in applications and presentations to quickly give insight into complicated issues.The "ActionScript Graphing Cookbook" shows you how to add your own charts to any ActionScript program. The recipes give step-by-step instructions on how to process the input data, how to create various types of charts and how to make them interactive for even more user engagement.Starting with basic ActionScript knowledge, you will learn how to develop many different types of charts.First learn how to import your data, from Excel, web services and more. Next process the data and make it ready for graphical display. Pick one of the many graph options available as the book guides you through ActionScript's drawing functions. And when you're ready for it, branch out into 3D display.The recipes in the "ActionScript Graphing Cookbook" will gradually introduce you into the world of visualization.

Who is this book for?

The "ActionScript Graphing Cookbook" is aimed at any ActionScript developer who wants to add data visualization to their skill set. The reader should be familiar with ActionScript basics, but no deep knowledge of any graphical functions is required.

What you will learn

  • Import data from various sources
  • Organize the various visual elements of a graph
  • Draw many types of charts, such as bar, line and pie charts, meters and many more
  • Make graphs interactive with hover and zoom effects
  • Work with geographical data and maps
  • Animate graphs with real time data
  • Show and interact with network displays
  • Discover three dimensional drawing and graphing
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Nov 21, 2012
Length: 288 pages
Edition : 1st
Language : English
ISBN-13 : 9781849693202
Category :
Languages :

What do you get with Print?

Product feature icon Instant access to your digital copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Redeem a companion digital copy on all Print orders
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Publication date : Nov 21, 2012
Length: 288 pages
Edition : 1st
Language : English
ISBN-13 : 9781849693202
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 153.97
C++ Game Development By Example
$49.99
ActionScript Graphing Cookbook
$48.99
HTML5 Graphing and Data Visualization Cookbook
$54.99
Total $ 153.97 Stars icon

Table of Contents

10 Chapters
Getting Started with Graph Drawing Chevron down icon Chevron up icon
Working with Data Chevron down icon Chevron up icon
Creating Bar Charts Chevron down icon Chevron up icon
Drawing Different Types of Graphs Chevron down icon Chevron up icon
Adding Interaction Chevron down icon Chevron up icon
Mapping Geographical and Spatial Data Chevron down icon Chevron up icon
Animating a Graph Chevron down icon Chevron up icon
Creating a Relational Network Chevron down icon Chevron up icon
Creating Three-Dimensional Graphs Chevron down icon Chevron up icon
Working with Various 3D Graph Types Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Full star icon 5
(1 Ratings)
5 star 100%
4 star 0%
3 star 0%
2 star 0%
1 star 0%
Igor Jan 29, 2013
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book has all that you need for creating math graphs. The concept of the book is learning by exampleif you learn this way than this is book for you. Every problem is firstly explained and then the solutionfor the problem is presented with code. There are some more useful information's after that.This book does not concentrate on explaining how sprites, movieclips and animation can bedrawn with ActionScript it is mainly for graphs that are used in different fields statistics,mathematics and other similar fields. So if you need that than this is book for you.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the digital copy I get with my Print order? Chevron down icon Chevron up icon

When you buy any Print edition of our Books, you can redeem (for free) the eBook edition of the Print Book you’ve purchased. This gives you instant access to your book when you make an order via PDF, EPUB or our online Reader experience.

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
Modal Close icon
Modal Close icon