Welcome to the second part of the MovieClipLoader tutorial. It's recommended (but not essential) that you work through the first part before reading any further.
This tutorial is going to start by identifying a common problem, and then we are going to use the MovieClipLoader class to provide the solution to it. The problem is one that has been the cause of a great many forum threads since the release of Flash MX, and goes something like this:
Hi, I dynamically created a bunch of movieclips and assigned
each of them an event handler. Then I loaded content in to
these clips, but I can't get the event handlers to work!
Here's my code [insert reams of spaghetti-like code here].
What am I doing wrong Please help!!!
Okay, so first we need to identify the cause of this problem here and it is this: when content is loaded into a movie clip the movie clip gets reset - this means that any code you had previously assigned to it goes the way of the Dodo. This doesn't pose too much of a problem with movie clips that have been placed manually on stage during authoring, because any code you have assigned directly to the movie clip, by way of an onClipEvent, will survive, but it does pose a problem for dynamically created clips, because we have to assign event code to these remotely at run-time.
How do we get around this problem? There are various ways around it, and since there are bountiful forum threads covering the topic I won't discuss it too deeply here, but whether it's an onLoad event or an onPress event, if we're loading external content in to flash we can achieve what we want by taking advantage of our friend, the MovieClipLoader class.
You may recall that at the beginning of the first tutorial I said this: "If you have ever tried to load an external jpeg or swf in to a flash movie, it is likely you will have encountered a situation where you need to trigger an event based upon completion of that loading process." We have already taken a look at the callbacks belonging to the movieclip loader, and so hopefully you will be able to see where we're going with this. In my example we're going to be creating functionality akin to that of a thumbnail gallery. We will load a set of jpgs into dynamically created movieclips, and we want each of these movieclips to possess their own onPress events. Will will avoid our code-wipe-out problem by assigning the events to the clips after the content has loaded in.
Before we begin I want to re-iterate a couple of points (99% of problem emails I get are due to these). Firstly, make sure you are exporting your swf as Flash 7 and AS2. Also, when you test your movie you should do so through a browser, else you may get odd results for some of the callbacks - it shouldn't affect the callback we're using here, but if you start modifying the code, then being aware of this will prevent you from puzzling as to why your file appears to be partially broken. We're also going to make use of a listener object, so it will help if you have a basic understanding of listeners and what they do. If you haven't used listeners before then read Senocular's excellent tutorial which can be found here.
Right, we know our problem, we have an idea of the solution, so let's actually write some code. You may be glad to know that there's relatively little code to write =)
1. Open up a new fla and save it as "tutorial_loop.fla".
2. Either create four thumbnail images 100*100px using any image software, or use the images provided in the zipped example, and save them in the same location as the fla. By the way, if anyone knows who to give credit to for those excellent pics (and the ones I used in the first tutorial) please let me know!
3. Create a dynamic textbox, aprox 300*300px with a size 12 font, and give it a border so we can see where it is on stage. Make it multiline and give it an instance name of "debug". Place the textbox on the stage so that there is at least 110px of spare space above it.
4. Create a square of any colour, make it 100px by 100px and turn it in to a movie clip. Delete it from the stage. Now, by right-clicking on it's symbol in the library (apple-click for Mac users) give it a linkage name of "img" and set it to export in the first frame by ticking the relevant checkbox. Of course, our clip could just as well be empty, but the content we load in will replace the square anyway, and I prefer this method of creating 'empty' clips.
5. Create another layer in the timeline (above the one holding the textbox). This is where we'll place our actionscript. Add a stop(); command to the frame.
6. Now we're going to define an instance of our MovieClipLoader, and also a generic object, which we will use as our listener, so add the following code to the actionscript frame:
myMCL = new MovieClipLoader(); //define MovieClipLoader
myListener = new Object(); //define listener
7. Next we want to define what will happen when our listener gets notified of the onLoadComplete event. If you remember, this is one of the MovieClipLoader's callback functions and it notifies us when the loading process is complete. Here we are assigning it to the listener object, rather than the MCL object, but when we subscribe the listener to the MCL (to 'listen out' for MCL events) it will have the same effect.
If we are sure that the loading process has completed, then we know it is now safe to assign our onPress event handler to the movieclip without it being wiped out. So, within our onLoadComplete we add the handler. Add the following code to the actionscript frame:
myListener.onLoadComplete = function(targetMC){
debug.text += "LOADING OF " + targetMC
+ " COMPLETE" + newline;
targetMC.onPress = function() {
debug.text += newline
+ "targetMC = " + targetMC._name;
}
}
Note: I have wrapped some of the above code on to seperate lines for tutorial formatting purposes. This does not affect the fla.
You may have noticed that the name of the movie clip which has finished loading is automatically sent to our onLoadComplete function as an argument, and so we can always tell which movie it is that has finished loading. Here I tell Flash to send information to the debug box when the movie finishes loading, and again when it is clicked.
8. Now we're going to create a function containing a loop. The loop attaches our img-holder mc from the library, creating four, evenly spaced instances of it, and using the MovieCLipLoader's loadClip() method, we start the loading of images 01.jpg to 04.jpg into the relevant clips. Add this code to the actionscript frame:
function initClips(){
for (i=1; i<=4; i++){
this.attachMovie("img", "img" + i, i);
this["img"+i]._x = i*110;
myMCL.loadClip("0" + i + ".jpg" ,
this["img"+i]); //code wrapped
}
}
9. That's almost it. Now all we have to do is assign the listener and call the duplicating function that we just wrote. This is easily done with these two lines of code:
myMCL.addListener(myListener);
initClips();
As you can see, we add our object as a listener to our MovieClipLoader instance before calling the initClips() function. When we click each clip its name will appear in the debug window. This works because the code was assigned after the images were loaded in. Our code is also pretty minimal. There was no need for long complicated checking loops. MovieClipLoader took care of that for us.
Okay, so our code should look like this:
..and our file should look and act something like this. If it doesn't work you can always download the example fla I have provided and check how I set up the fla.
That's it for this tutorial. Hopefully you can see just how advantageous using the MovieClipLoader class can be. Anything that saves you writing lots of code with no [obvious] overhead can't be that bad eh!
--------------------------------------------------------------------------------
This tutorial is going to start by identifying a common problem, and then we are going to use the MovieClipLoader class to provide the solution to it. The problem is one that has been the cause of a great many forum threads since the release of Flash MX, and goes something like this:
Hi, I dynamically created a bunch of movieclips and assigned
each of them an event handler. Then I loaded content in to
these clips, but I can't get the event handlers to work!
Here's my code [insert reams of spaghetti-like code here].
What am I doing wrong Please help!!!
Okay, so first we need to identify the cause of this problem here and it is this: when content is loaded into a movie clip the movie clip gets reset - this means that any code you had previously assigned to it goes the way of the Dodo. This doesn't pose too much of a problem with movie clips that have been placed manually on stage during authoring, because any code you have assigned directly to the movie clip, by way of an onClipEvent, will survive, but it does pose a problem for dynamically created clips, because we have to assign event code to these remotely at run-time.
How do we get around this problem? There are various ways around it, and since there are bountiful forum threads covering the topic I won't discuss it too deeply here, but whether it's an onLoad event or an onPress event, if we're loading external content in to flash we can achieve what we want by taking advantage of our friend, the MovieClipLoader class.
You may recall that at the beginning of the first tutorial I said this: "If you have ever tried to load an external jpeg or swf in to a flash movie, it is likely you will have encountered a situation where you need to trigger an event based upon completion of that loading process." We have already taken a look at the callbacks belonging to the movieclip loader, and so hopefully you will be able to see where we're going with this. In my example we're going to be creating functionality akin to that of a thumbnail gallery. We will load a set of jpgs into dynamically created movieclips, and we want each of these movieclips to possess their own onPress events. Will will avoid our code-wipe-out problem by assigning the events to the clips after the content has loaded in.
Before we begin I want to re-iterate a couple of points (99% of problem emails I get are due to these). Firstly, make sure you are exporting your swf as Flash 7 and AS2. Also, when you test your movie you should do so through a browser, else you may get odd results for some of the callbacks - it shouldn't affect the callback we're using here, but if you start modifying the code, then being aware of this will prevent you from puzzling as to why your file appears to be partially broken. We're also going to make use of a listener object, so it will help if you have a basic understanding of listeners and what they do. If you haven't used listeners before then read Senocular's excellent tutorial which can be found here.
Right, we know our problem, we have an idea of the solution, so let's actually write some code. You may be glad to know that there's relatively little code to write =)
1. Open up a new fla and save it as "tutorial_loop.fla".
2. Either create four thumbnail images 100*100px using any image software, or use the images provided in the zipped example, and save them in the same location as the fla. By the way, if anyone knows who to give credit to for those excellent pics (and the ones I used in the first tutorial) please let me know!
3. Create a dynamic textbox, aprox 300*300px with a size 12 font, and give it a border so we can see where it is on stage. Make it multiline and give it an instance name of "debug". Place the textbox on the stage so that there is at least 110px of spare space above it.
4. Create a square of any colour, make it 100px by 100px and turn it in to a movie clip. Delete it from the stage. Now, by right-clicking on it's symbol in the library (apple-click for Mac users) give it a linkage name of "img" and set it to export in the first frame by ticking the relevant checkbox. Of course, our clip could just as well be empty, but the content we load in will replace the square anyway, and I prefer this method of creating 'empty' clips.
5. Create another layer in the timeline (above the one holding the textbox). This is where we'll place our actionscript. Add a stop(); command to the frame.
6. Now we're going to define an instance of our MovieClipLoader, and also a generic object, which we will use as our listener, so add the following code to the actionscript frame:
myMCL = new MovieClipLoader(); //define MovieClipLoader
myListener = new Object(); //define listener
7. Next we want to define what will happen when our listener gets notified of the onLoadComplete event. If you remember, this is one of the MovieClipLoader's callback functions and it notifies us when the loading process is complete. Here we are assigning it to the listener object, rather than the MCL object, but when we subscribe the listener to the MCL (to 'listen out' for MCL events) it will have the same effect.
If we are sure that the loading process has completed, then we know it is now safe to assign our onPress event handler to the movieclip without it being wiped out. So, within our onLoadComplete we add the handler. Add the following code to the actionscript frame:
myListener.onLoadComplete = function(targetMC){
debug.text += "LOADING OF " + targetMC
+ " COMPLETE" + newline;
targetMC.onPress = function() {
debug.text += newline
+ "targetMC = " + targetMC._name;
}
}
Note: I have wrapped some of the above code on to seperate lines for tutorial formatting purposes. This does not affect the fla.
You may have noticed that the name of the movie clip which has finished loading is automatically sent to our onLoadComplete function as an argument, and so we can always tell which movie it is that has finished loading. Here I tell Flash to send information to the debug box when the movie finishes loading, and again when it is clicked.
8. Now we're going to create a function containing a loop. The loop attaches our img-holder mc from the library, creating four, evenly spaced instances of it, and using the MovieCLipLoader's loadClip() method, we start the loading of images 01.jpg to 04.jpg into the relevant clips. Add this code to the actionscript frame:
function initClips(){
for (i=1; i<=4; i++){
this.attachMovie("img", "img" + i, i);
this["img"+i]._x = i*110;
myMCL.loadClip("0" + i + ".jpg" ,
this["img"+i]); //code wrapped
}
}
9. That's almost it. Now all we have to do is assign the listener and call the duplicating function that we just wrote. This is easily done with these two lines of code:
myMCL.addListener(myListener);
initClips();
As you can see, we add our object as a listener to our MovieClipLoader instance before calling the initClips() function. When we click each clip its name will appear in the debug window. This works because the code was assigned after the images were loaded in. Our code is also pretty minimal. There was no need for long complicated checking loops. MovieClipLoader took care of that for us.
Okay, so our code should look like this:
..and our file should look and act something like this. If it doesn't work you can always download the example fla I have provided and check how I set up the fla.
That's it for this tutorial. Hopefully you can see just how advantageous using the MovieClipLoader class can be. Anything that saves you writing lots of code with no [obvious] overhead can't be that bad eh!
--------------------------------------------------------------------------------
回复Comments
作者:
{commentrecontent}