官术网_书友最值得收藏!

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.

主站蜘蛛池模板: 海晏县| 屯昌县| 高阳县| 龙泉市| 岳阳县| 郓城县| 宁城县| 腾冲县| 瑞金市| 莫力| 滨州市| 扶风县| 海安县| 岳阳县| 泾源县| 阜南县| 枝江市| 云阳县| 永昌县| 镇沅| 承德县| 西乌珠穆沁旗| 甘肃省| 策勒县| 武川县| 浮山县| 玉林市| 弥勒县| 华坪县| 雅江县| 虞城县| 新郑市| 东海县| 会宁县| 昭苏县| 平武县| 福清市| 彰化县| 普定县| 遂川县| 杂多县|