Preloaders 3 : Drawing API



The Flash movie at left shows a standard loading bar displaying the percentage of the content loaded for the movie. The animation is created by constantly redrawing a rectangle using the new drawing API in Flash MX. Textfields at left and right show numerical values of the amount loaded and total amount of kilobytes for the movie. To repeat the animation once the movie is fully loaded, simply refresh this browser window.

Download the sourcefile here.

In the first of our preloader tutorials, "Preloaders 1 : Text Feedback," we looked at assessing the loading information and displaying it in a readable form for the viewer. We followed with "Preloaders 2 : Loading Bar," in which we graphically displayed this information as a traditional loading bar using Flash library symbols. In this tutorial, we will build upon this idea and draw our loading bar instead using the new drawing API (Application Programming Interface).

With the drawing API, Flash coders can now create graphics at runtime using a set of simple new commands. This tutorial will not be a run-down of these commands (that's another tutorial in itself!), but a practical application. We will use the commands to draw and redraw our loading bar to display the percentage of bytes loaded. Let's take a look at how to accomplish this.


  1. Open up the finished file from the last tutorial. If you'd like, you can just download my version here. Save this file as "preloaders3.fla".
  2. Delete the loading bar graphic and textfields from the stage. The stage should now be empty. We will be producing our entire preloader with code! (Because of this, you may also delete the "graphics layer" in your timeline so you are left with only the "code" layer.)
  3. Open the Actionscript editor for frame 1 of the "code" layer. The code from the previous tutorial should be there. We are going to add a few lines before the code already present:


    barColor = 0x6666CC;
    barOutlineColor = 0xAFAFE4;
    barOutlineThickness = 2;
    barFullWidth = 200;
    barFullHeight = 40;
    barCenterX = Stage.width/2;
    barCenterY = Stage.height/2;
     
    this.createEmptyMovieClip("bar", 0)
    this.createEmptyMovieClip("outline", 1)
    bar._x = outline._x = barCenterX - barFullWidth/2;
    bar._y = outline._y = barCenterY - barFullHeight/2;

    These variables will control the appearance of our loading bar, and each one has been given a descriptive name so you are clear of its purpose. By placing these variables at the top of our code, it is easy to go in later and alter our loading bar's appearance.

    Next in our code we create two new movieclips to house our drawings for the bar. bar will hold the solid fill bar, while outline will hold the bar's outline. We place these clips so that their registration points will be at the top let of the bar graphic (this will make it easier to draw, as you will see).

  4. After defining our bar's appearance and creating the clips, we need to create a TextFormat object to control our textfields' appearance, which will also be created dynamically. If you've yet to use TextFormat, it's a great way to control the look of text, similar to defining a style in a word-processing program (or a style for text with CSS).


    loadingTF = new TextFormat();
    loadingTF.font = "_sans";
    loadingTF.color = 0xAFAFE4;
    loadingTF.size = 22;
    loadingTF.align = "right";

    In these lines we create a new TextFormat object and adjust four of its many properties (If you do not explicitly assign a value to a property, it will remain null, which will not affect the textfield in any way. This will prove useful, as we will see in a moment.). Notice that we have assigned "_sans" as the TextFormat's font. This will be a system font on the user's computer.

    We will be using this TextFormat for both textfields to be created, but ideally we would like the "totalBytes" textfield on the right to be left-aligned, not right. An easy way to fix this problem is to create another TextFormat to control this left-alignment. One of the great features of the TextFormat object is that you can apply multiple instances to a single textfield. The only properties that are overwritten are those that do not have a value of null in the new TextFormat. So if we apply loadingTF to the textfield at right, then apply another TextFormat that only has the align property assigned, then that wil be the only property overwritten. Let's see how this is done.

  5. Place these lines after the loadingTF definition:


    leftAlignTF = new TextFormat();
    leftAlignTF.align = "left";

    That's it! This new TextFormat can be applied over loadingTF. We'll do that next, after the creation of our textFields.

  6. This code directly follows the lines from the last step:


    x = barCenterX - barFullWidth/1.8;
    this.createTextField("loaded", 10, x, barCenterY, 0, 0);
    loaded.setNewTextFormat(loadingTF);
    loaded.selectable = 0;
    loaded.autosize = "right";
    loaded.text = "0Kb";
    loaded._y -= loaded.textHeight/2;
     
    x = barCenterX + barFullWidth/1.8;
    this.createTextField("total", 11, x, barCenterY, 0, 0);
    total.setNewTextFormat(loadingTF);
    total.setNewTextFormat(leftAlignTF);
    total.selectable = 0;
    total.autosize = "left";
    total.text = "0Kb";
    total._y -= total.textHeight/2;
     
    delete x;

    Quite a few lines to look at here, but if you break it down they are pretty easy to deal with. The first thing we do is find the x position of our loaded textfield by using the dimensions and coordinates from our opening variables. We create the textfield on the next line at a depth of 10, sending the x variable we just set. We don't have to give a width and height (the two final arguments in the createTextField call) since we set the autoSize property to "right" in a few lines. This means that the textfield will automatically resize from the right to fit whatever text we place inside it. Handy. We also give the textfield the TextFormat we created earlier. We use the method setNewTextFormat so that the TextFormat is applied to any text that is later placed inside the textfield. Finally, we adjust the _y property of the textfield based on the height of its text. This will center the textfield nicely on the bar.

    The next block creates our total textfield, which will display the total kilobytes of our movie. We apply the loadingTF TextFormat, though immediately after we apply the leftAlignTF TextFormat as well. That's all we need to do to have total look the same as loaded, but have a different alignment.

    Now! We have clips to hold the graphics and textfields to hold the text. All we have left to do (since we can use nearly all of the code from the last tutorial because the concepts are the same) is draw the graphics. You will learn that there are certain functions that will come in handy if you use the drawing API a lot. Such a function is one to draw a box.

  7. Place these lines after the code we just typed to create the textfields:


    MovieClip.prototype.drawBox = function(left, top, right, bottom) {
      this.moveTo(left, top);
      this.lineTo(right, top);
      this.lineTo(right, bottom);
      this.lineTo(left, bottom);
      this.lineTo(left, top);
    }

    Since we will be drawing boxes more than once in our code, it makes sense to contain the code to do so within a function. We actually create the function as a method of the MovieClip object (by placing it within the prototype property, which every instance of MovieClip has access to) so that we can call the function just as we would any other drawing method (e.g., lineTo(), moveTo(), etc.). The method simply draws a box (just as its name implies!) based on the four coordinates sent to the method as arguments.

  8. To call this function for outline, place these lines next in the code:


    outline.lineStyle(barOutlineThickness, barOutlineColor, 100);
    outline.drawBox(0, 0, barFullWidth, barFullHeight);

    Simple now, yes? We set outline's lineStyle (sending thickness, color and alpha values) and call the drawBox method with the appropriate box dimensions. We should get a nice box outline from this!

    As for the rest of the code, we can salvage 99% of what we used last tutorial. This is because, as I have stressed, the concept of a preloader remains the same, it is the representation that differs. In the last tutorial, we represented the percent loaded by scaling a rectangle graphic. Here, we instead draw the rectangle with the drawing API. Therefore, we need to replace the lines that scaled our rectangle symbol with ones that will draw a rectangle instead.

  9. Below is the full code from the last tutorial, with the lines to be deleted in white:


    assessLoad = function(clip, endPreloadFunc) {
      var kbLoaded = clip.getBytesLoaded()/1024;
      var kbTotal = clip.getBytesTotal()/1024;
      var percent = Math.floor(kbLoaded/kbTotal * 100);
      loaded.text = Math.floor(kbLoaded) + "Kb";
      total.text = Math.floor(kbTotal) + "Kb";
      bar._xscale = percent;
      if ((kbLoaded/kbTotal == 1) && kbLoaded > 1) {
      endPreloadFunc();
      }
    }
     
    endPreload = function() {
      clearInterval(preload);
      this.play();
    }
     
    bar._xscale = 0;
    preload = setInterval(assessLoad, 100, this, endPreload);
    stop();

  10. Now in place of those lines, insert the following (again, in white). Also note that we are changing the line where we set the percent variable.


    assessLoad = function(clip, endPreloadFunc) {
      var kbLoaded = clip.getBytesLoaded()/1024;
      var kbTotal = clip.getBytesTotal()/1024;
      var percent = kbLoaded/kbTotal;
      loaded.text = Math.floor(kbLoaded) + "Kb";
      total.text = Math.floor(kbTotal) + "Kb";
      var right = barFullWidth * percent;
      bar.clear();
      bar.beginFill(barColor, 100);
      bar.drawBox(0, 0, right, barFullHeight);
      bar.endFill();
      if ((kbLoaded/kbTotal == 1) && kbLoaded > 1) {
      endPreloadFunc();
      }
    }
     
    endPreload = function() {
      clearInterval(preload);
      bar.removeMovieClip();
      outline.removeMovieClip();
      loaded.removeTextfield();
      total.removeTextfield();
      this.play();
    }
     
    preload = setInterval(assessLoad, 100, this, endPreload);
    stop();

    OK, nearly there! You should be able to see that, using the percent variable (which we calculate now as a true percent between 0 and 1), we adjust the right side of our bar graphic. We then clear the previously drawn graphic, and redraw the bar with our new value for the right side of the bar. The changes in the endPreload function are there to remove all of our dynamically-placed graphics. Other than that, the code remains the same!

    Go ahead and test your movie now (using Show Streaming, still with the large graphic placed in frame 2 of the movie, as was discussed in our two previous tutorials) to see the bar drawn across the stage!


Not much visually has changed from the last tutorial, but we have made the code a bit easier to update and change the appearance of our preloader. You could easily adapt this code and make a loading bar component that you could drag and drop into different projects, or attach through code as you load different content into your site. Of course, you also do not have to be limited by the standard box. You can see that all we are doing is affecting a value with our current percent. I chose to affect the right side of a rectangle, but you can affect anything else you wish that would inform the user of the progress of the load.

In the next and final preloaders tutorial, I will show you how you can use the code we discussed here to create dynamic masking effects for your preloaders. It's a small alteration to the code, but will give you access to a multitude of effects. Till then, explore and enjoy!