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

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.