15 Replies Latest reply on Jun 6, 2007 8:29 PM by Peter Pawinski

    MovieClipLoader class

    Peter Pawinski
      For some reason, I'm having difficulty wrapping my head around how to implement and use the MovieClipLoader class. Here's where I'm stuck. I have a bit of code that looks like this:


      function showImage(filename:String):Void {
      var image:MovieClip = imagePlaceholder_mc.image_mc;
      image.loadMovie(filename);
      //Center images
      xPos = (900 - image._width)/2;
      yPos = (600 - image._height)/2;
      image._x = xPos;
      image._y = yPos;
      imagePlaceholder_mc._alpha = 0;
      imagePlaceholder_mc.onEnterFrame = fadeIn;

      }

      Now, whenever showImage() is called, the picture loads and properly fades in. However, the image is not correctly centered. However, if showImage is called a second time on the same image, THEN the image properly centers. Basically, showImage uses the last ._width and ._height values. I assume this is because the clip hasn't finished loading when xPos and yPos are set, and that if I had the calculations occur when the .jpg is completely loaded, then the correct results will occur.

      However, I can't seem to figure out where to put my MovieClipLoader class, where to stick the listeners, or anything. I'm having some sort of problem conceptualizing how the class is supposed to work, and for some reason the tutorials are not helping me out. If it were explained to me in relation to the code I have above, it would help.

      Thanks,
      Peter
        • 1. Re: MovieClipLoader class
          crazyjoemilan Level 2
          you assume correctly about your problem, and the MovieClipLoader class is, in fact, one way to do it. You could also use getBytesLoaded() and getBytesTotal() to ping your loading MovieClip, and only call the function when they are equal, and greater than 0.

          HmcH
          • 2. Re: MovieClipLoader class
            Peter Pawinski Level 1
            quote:

            Originally posted by: Mr Helpy mcHelpson
            You could also use getBytesLoaded() and getBytesTotal() to ping your loading MovieClip, and only call the function when they are equal, and greater than 0.

            HmcH


            Wouldn't I then have to put this in some sort of loop? Would it be an onEnterFrame or something? What's the cleanest and most elegant way of doing it? Would it be the MovieClipLoader or the other method?

            • 3. MovieClipLoader class
              Peter Pawinski Level 1
              OK, so I created an onEnterFrame that checks for bytesLoaded and bytesTotal. It works. Images are properly centered now.
              However, I can't use the fadeIn function now. The fadeIn function looks like this:

              function fadeIn():Void {
              this._alpha += FADESPEED;
              if (this._alpha > 100) {
              this._alpha = 100;
              delete this.onEnterFrame;
              }
              }

              The problem is "this" before pointed to imagePlaceholder_mc. Now it just points to level0. Secondly, can I nest onEnterFrames like this? It looks wrong.

              Anyhow, my revised code that works, minus the fade effect:

              imagePlaceholder_mc.onEnterFrame = function() {
              if (image.getBytesLoaded() == image.getBytesTotal()) {
              xPos = (900-image._width)/2;
              yPos = (600-image._height)/2;
              image._x = xPos;
              image._y = yPos;
              imagePlaceholder_mc._alpha = 100;
              delete this.onEnterFrame;
              }
              }

              Where I have "imagePlaceholder_mc._alpha" is where I would want to call the fadeIn() function.
              • 4. Re: MovieClipLoader class
                Rothrock Level 5
                Can't really explain it in terms of your code above because it is different that your code above. The MCL just gives some nice packaging to starting, progressing through, and ending, the load of external assets. The listeners just listen for the different "events" in this process and then can run certain bits of code when those events happen.

                So lets go to it. We start out well enough:

                function showImage(filename:String):Void {

                Then we need to make an instance of our MCL. It is also possible to have it outside your function, but for now lets keep it inside.

                var myMCL:MovieClipLoader=new MovieClipLoader;

                Next we need to make an object to attach the various events to. There are a lot of ways they could have designed this, but this is how they did it so that is what we do!

                var myListener:Object=new Object()

                Now there are several different events that the MCL might have, but for the moment we are going to worry about only one of them. You want to do something when the external asset is fully loaded – you can't set the width or height until after the whole thing is done.

                myListener.onLoadInit=function(target:MovieClip){
                Pos = (900 - target._width)/2;
                yPos = (600 - target._height)/2;
                target._x = xPos;
                target._y = yPos;
                target._parent._alpha = 0;
                target._parent.onEnterFrame = fadeIn;
                }

                Notice how basically your same code goes in there, but with the difference of target? (BTW, I could have called that grapefruit or anything I wanted, but target seemed good.) That is because the onLoadInit event returns a reference to the thing that has just had content loaded into it. So we can use that instead of having to hard code the names of our movie clips. That makes it a lot more flexible.

                Okay we could now issue our load, close up the braces, and be done with it. But we still have one more thing. Let's look at what we have. We've made a function that sets up an MCL, makes and Object to hold listeners, and set up an event inside that object. But we still haven't told our MCL instance that it needs to report its events to that object.

                It is a great philosophical debate of whether events happen if there is nothing there to listen for them! :) But on the practical side, nothing will happen if we don't tell flash to listen for them. That is way we need the next line:

                myMCL.addListener(myListener);

                That tells our MCL that when it has events it needs to tell myListener about them. Now the MCL has many events onLoadStart, onLoadProgress, etc. and it will dutifully tell our listener object about them. Inside that listener we have only set up an action for one of them, but hey, laissez les bon temps rouler.

                So finally we can issue our load statement and close up the braces.

                myMCL.loadClip(filename);
                }

                So what happens?

                You call your function and pass it the filename.
                An MCL is created.
                A listener object is created.
                Object is given an event handler function.
                The MCL is told to report its events to that Object.
                The MCL starts loading the file.
                The MCL has a onStartLoad event and reports it to the object.
                Nope no handler for that, nothing to do.
                Several times in a row the MCL has an onLoadProgress event, and reports it.
                Nope no handler for that, nothing to do.
                etc.
                Finally there is an onLoadInit event – the file is ready to be mucked with. The MCL reports it to the object, and hey there is something to do.
                So the MCL tells the objects onLoadInit function, "I just Inited, the following clip."
                The function then takes that information and applies the things you specified.

                And that is pretty much it.

                A couple of notes. The onLoadProgess event doesn't happen when you are testing locally. So you won't see it.

                It is a good practice to get into that when you are done with something you remove the listener. So you might want to add the following line to your onLoadInit function.

                myMCL.removeListener(myListener);

                (At least I think that is a good idea. I haven't done that myself in the past, but I have recently become much more aware of how important it is – at least generally – to remove listeners. So if you get an error just remove that.)

                • 5. Re: MovieClipLoader class
                  Peter Pawinski Level 1
                  Awesome reply! I'm eternally grateful. The explanation really is helping me understanding the logical steps in setting up and using the MovieClipLoader class. I'll plug it into my code and see how it goes!
                  • 6. Re: MovieClipLoader class
                    Peter Pawinski Level 1
                    Ok...I tried what I think I was supposed to do, but it didn't do anything. I inserted a trace, and the onLoadInit code is never executed:

                    function showImage(filename:String):Void {
                    var myMCL:MovieClipLoader = new MovieClipLoader();
                    var myListener:Object = new Object();
                    myListener.onLoadInit = function(target:MovieClip) {
                    trace("I am here!");
                    xPos = (900 - target._width) / 2;
                    yPos = (600 - target._height) / 2;
                    target._x = xPos;
                    target._y = yPos;
                    target._parent._alpha = 0;
                    target._parent.onEnterFrame = fadeIn;
                    };
                    myMCL.addListener(myListener);
                    myMCL.loadClip(filename);
                    }

                    What am I missing?


                    • 7. Re: MovieClipLoader class
                      Peter Pawinski Level 1
                      I guess my questions are thus:

                      1) When myMCL.loadClip(filename) is executed, where is the content loaded? Just into memory?

                      2) I have an imagePlaceholder on the stage, and image_mc is where the movie clip is loaded when I run the original code. So it loads and is placed on the area of the stage which I reserved for displaying images. The above code doesn't seem to indicate that the image needs to be placed in that location. How do I tell it where to put my image?

                      I guess that basically is where I'm running into conceptual problems. showImage is run from various functions. I have one function which is a slideshow and it calls showImage to place images one after another on the stage. I have another function which calls showImage when a user clicks on a thumbnail, that sort of stuff. So showImage is called from various functions, but in each case, the image that is loaded should be displayed at _level0.ImagePlaceholder_mc

                      • 8. Re: MovieClipLoader class
                        Rothrock Level 5
                        Yup. I'm a silly. And here is a great learning moment. You have hit it right on the head with your two questions – we haven't told the MCL WHERE to load the asset. See? You know more than you thought and you just psyched yourself up to not trust yourself.

                        When in doubt check the help files. A sensible place to start would be the loadClip method – it just seems like a place where maybe we tell the MCL WHAT to load WHERE.

                        Sure enough in the help files I forgot to include the second argument : target.

                        So we could just add that as in:

                        myMCL.loadClip(filename,_level0.ImagePlaceHolder_mc);

                        But why not make this a bit more flexible. How about we send it as part of the show image function, that way you could use it to load into different clips if you needed to.

                        function showImage(filename:String,target:MovieClip){

                        and then later:

                        myMCL.loadClip(filename,target);

                        • 9. Re: MovieClipLoader class
                          Peter Pawinski Level 1
                          YIPPEEE!!!!

                          It works now! Actually, it was _level0.imagePlaceholder_mc.image_mc where I needed the file to load, but I think now that I've got a better understanding of the MovieClipLoader class, I should be able to simplify the code a little.

                          Awesome!
                          • 10. Re: MovieClipLoader class
                            Rothrock Level 5
                            Cool. Glad that worked out for you. Here is a little bit of a trick I like to use.

                            Using _root and/or _level0 can be a bit of a trap. If you later try and load things into other things and such. So instead at the beginning of your code do this:

                            var home:MovieClip=this;

                            Then anyplace you are tempted to use _root or _level0, do this instead:

                            home.imagePlaceHolder.etc.andSoOn

                            Have fun and try some different experiments with the MCL. It is really quite flexible and pretty easy to use once you get the hang of it.
                            • 11. Re: MovieClipLoader class
                              crazyjoemilan Level 2
                              MovieClipLoader is always the preferred way. And thanks to Rothrock for answering the actual how-to. I got called away to a meeting in the middle of my post.

                              function fadeIn():Void {
                              this._alpha += FADESPEED;
                              if (this._alpha > 100) {
                              this._alpha = 100;
                              delete this.onEnterFrame;
                              }
                              }

                              Check out the Tween class to replace this. kirup.com's tutorial is a good one, go there and check it out. It's very nice!

                              Joe
                              • 12. Re: MovieClipLoader class
                                Rothrock Level 5
                                Back in the day, the coded preloader was the only way to go (in the snow, uphill both ways, with wolves nipping at your heels) but the MCL (and now the Loader class in AS3) is the way to go.

                                But there are some very important concepts and skills to be learned by making an old-school preloader. So if you haven't done so I would recommend trying it just to learn.
                                • 13. MovieClipLoader class
                                  Peter Pawinski Level 1
                                  I actually am aware of the Tween class--I had one version of the website coded that way. I just figured a simple transition like this doesn't need the Tween class when it's only a couple lines of code. However, I probably will eventually expand my fadeIn function to something more generic (allowing users to tweak their preferred transitions in the XML file) and will end up using the Tween class anyway.

                                  I did have one issue--I don't know anything about old school preloaders or any of that. However, I uploaded my project to my website, and it only sort-of works. I wonder if it's a preloading issue. When run off my hard drive, it works. When I upload it, the opening page doesn't quite work, but subsequent pages (galleries) work. They all run the same bit of showImage code. I do notice that when the opening page opens, it says "waiting for ... " in the status bar instead of "read."

                                  If you want to see the problem, lookie here:

                                  http://testproject.peterpawinski.com

                                  (It's still very very much a sketch. The little slide panel on the bottom needs to be tidied up for vertical photos. The drop down menu could be a tad neater, etc.) If you load it up, there should be an opening image. If you go to Galleries > and pick any of the first two, they are functional. (The other menu options do not have targets yet.)

                                  I can't figure out why that first image opens locally, but not off the server. Every other image is fine. The target path should be fine (just "Images/Slideshow"). I'm wondering if that "waiting for testproject.peterpawinski.com..." immediately flags anything to you.
                                  • 14. Re: MovieClipLoader class
                                    Rothrock Level 5
                                    Most likely your initial swf is having to load itself before it is able to execute the code for the first frame. That is where the old-school type loader comes in. I don't know how you have your FLA laid out, but you could add a frame a the very beginning something like this:

                                    stop();
                                    this.onEnterFrame=function(){
                                    if(this.getBytesLoad() == this.getBytesTotal() && this.getBytesTotal>4){
                                    this.gotoAndStop(2);
                                    } else {
                                    do some preloader stuff
                                    }
                                    • 15. Re: MovieClipLoader class
                                      Peter Pawinski Level 1
                                      quote:

                                      Originally posted by: Rothrock
                                      I don't know how you have your FLA laid out, but you could add a frame a the very beginning something like this:



                                      All my code is on Frame 1. I'll insert a frame before it and see what happens. Thanks.