Workshop Chapter 13. Drawing Graphs

  •  Dynamic Text Labeling

In this workshop chapter, you'll draw graphs using the new drawing methods of the Movie Clip object. Without a clip on the stage, you'll create a bar chart that displays dynamic data. If you need to change the graph, you can just change a few variables. Figure W13.1 shows what you'll have at the end of this workshop.

Figure W13.1. You'll learn how to dynamically draw a graph, make shadows, fill with a pattern, and place text labels anywhere you please.


This workshop chapter is broken into two sections. First, you'll prepare and draw the graph using the drawing methods. Next, you'll add a few extra features (such as labels) using the TextField and TextFormat objects.

Using the Drawing Methods

In Chapter 12, "Objects," you learned all the Movie Clip's drawing methods. These methods make anything that's imaginable possible. The difficulty, however, lies in the "imagining" part. Everything in our graph is going to be drawn using code, so it will take some pre-visualization as we work. I guess all this is leading to my recommendation to draw a rough layout for your graph by hand in order to work up a few expressions to use when coding. That's how we'll start we'll draw something in draft form (see Figure W13.2).

Figure W13.2. A rough layout can help you to deduce the expressions you'll need to draw the graph.


Dynamic Text Labeling

Perhaps it was premature to start creating shadows and patterns of color before the graph had labels. I don't know which teacher told me, but a graph with no labels means nothing. In this part of the workshop chapter, you'll place labels on the vertical axis (one for vLabel and one for each bar) so that the user can see its value.

  1. To place a dynamically generated Text Field, you'll need to start with the graphing code from the first part of this workshop. Actually, you really only need the code through at least step 9. You'll start by creating an instance of the TextFormat object. Place the following four lines above all the rest of the code in the file:

    myFormat= new TextFormat();  myFormat.size=12;  myFormat.font="_sans";  myFormat.bold=true;

    You can use whichever font, size, and style you want. Just realize that the myFormat variable will be stored in the _root timeline.

  2. To display the value of vLabel on the graph, place the following code right inside the first with() statement (it should start with with(_root.graph){ as you can see in line 1 of step 8 earlier):

    1 targ=_root.graph;  2 targ.createTextField("myLabel",1, 0 ,0,0,0);  3 targ.myLabel.autoSize=true;  4 targ.myLabel.text=vLabel;  5 targ.myLabel.setTextFormat(_root.myFormat);

    The first line just specifies an absolute address for all subsequent addresses. Line 2 makes a new TextField instance (called myLabel) and places it in level 1 of the graph clip. Line 3 sets autoSize to true so that the margins adapt automatically. In line 4, I set myLabel's text to reflect the value of vLabel. Finally, the last line applies the myFormat format defined in step 1.

  3. The text should appear but in the wrong location. Its _y location should be the same as the variable vMax. To set the _x position, we can effectively make it right justified by moving the text to the left a value equal to its width. Here are two more lines of code that go right after the scripts added in step 2.

    targ.myLabel._y=vMax;  targ.myLabel._x= -1*targ.myLabel._width;

    You could actually subtract another 2 or 3 pixels to move the _x position a little farther if you think the right edge is too close to the graph.

  4. Before we add code inside the for loop to display a text field for each bar, realize that the createTextField() method specifies a level number into which the text resides. We now have text in level 1, so we should start with a higher level and keep placing each text field into new level numbers. The following code will label each bar. Place it anywhere inside the for loop inside the with() code (that is, after the line that reads: for (i=0; i<data.length; i++){ line 2 in step 8 noted previously):

    1 targ.createTextField("bar_"+i ,i+2, 0 ,0,0,0);  2 var thisText=targ["bar_"+i];  3 thisText.autoSize=true;  4 thisText.text=data[i];  5 thisText.setTextFormat(_root.myFormat);  6 thisText._y=0;  7 thisText._x=w+(i*1.5*w)- thisText._width/2;

    Line 1 just creates a new text field with an instance name of bar_0 (and then bar_1, and so on). Notice, however, that the new text field is placed in a level number 2 greater than the value of the iterant i because the vLabel text is in level 1. Then, in line 2, I store a reference to the current text field (into thisText) using the standard bracket reference so that I can save typing in the following five steps (where I format and then position it). The last line is just a modified version of the code used for calculating the bar's locations. I subtract half the width of the text field to make it appear center justified. (I could have set the _root.myFormat align property to "center", but then I'd have to remember to set it back if I expected it later to be, say, "left".)

  5. The horizontal spacing is great, but those labels really should appear right on the bar. (If we want labels on the base of the bars, we could do that separately.) Change the line where thisText's _y is set to read as follows:


    Again, I just stole some code from where the bars are being drawn. It actually works great, but if the text is the same color as the graph, you won't see it! To fix that, you can just pick a different color for the myFormat format (such as _root.myFormat.color=0x00FFFF;). Realize, however, that if you change the color before the myLabel instance has the setTextFormat() method applied (in step 2), you will color it too. Another alternative to make the text visible is to change the fill color in the bars.

  6. Regardless of whether you changed the color orientation, I think it makes sense to move the labels. Try this final version for how thisText gets its _y set:

    thisText._y=(data[i]/vLabel)*vMax - thisText._height;

    By simply moving the text up a value that matches its height, it appears on top of each bar.

    I'm sure we could spend a lot more time fine-tuning, but I want to show you one issue that will arise if you try to place both labels at the base of each bar and the values on top. The issue has to do with the level into which you instantiate the text fields. That is, using an expression such as i+2 works fine for the labels we've drawn, but it's slightly more complex when you make two labels for each iteration. Try the following two steps to see what I'm talking about.

  7. First, outside the with() statement, find where you set the values for the data variable (step 7 in the first section of this workshop chapter). Add this line of code right underneath:

    graph.labels=["Apples", "Oranges", "Pears"];

    The idea is that for each item in the data array, you now have an equivalent text label in the labels array.

  8. Then, back inside the for loop that's inside the with() statement (where you created the value labels), add the following code:

    targ.createTextField("label_"+i ,i+1+100, 0 ,0,0,0);  var thisText=targ["label_"+i];  thisText.autoSize=true  thisText.text=labels[i];  thisText.setTextFormat(_root.myFormat);  thisText._y=0  thisText._x=w+(i*1.5*w)- thisText._width/2;

    This looks pretty much the same, except in the fourth line, we grab a value out of the labels array (instead of data). Oh, and don't worry that we're storing a different reference in thisText. As long as we redefine that value before using it for the value text (bar_0 and so on), there's no problem. The key thing to notice is that in the first line, we're placing these new text fields way up in level 100 and greater. This solution falls apart when we have more than 100 bars. Perhaps you can figure out an expression that automatically places these "label" fields into even-number levels and the "value" text fields into odd-number levels.

This workshop chapter was a good exercise into practical uses for the drawing methods. As you have other ideas come to mind, it will be only a matter of applying the skills you have to solve the challenges. For example, because the graph is drawn dynamically, the data for the various points could be imported from a text file or online database. By the way, you can make an animated effect by repeatedly drawing slightly different graphs. You have to redraw everything for every step of the animation, so it might start bogging down, but you might be surprised with the performance.

The key concept I hope you take away from this workshop is that once you write all your various expressions, you can very easily apply them to complex drawing tasks. That is, the time upfront is well worth the investment.


ActionScripting in MacromediaR FlashT MX
ActionScripting in MacromediaR FlashT MX
Year: 2001
Pages: 41 © 2008-2017.
If you may any questions please contact us: