Log in

View Full Version : Ext Jpgs with loading bars - clean up actionscript + fade up/down



GordonBennett
10-01-2008, 11:42 AM
Hello

I've got a gallery i'm making in flash and need some help smoothing out the appearance of the loading process and also most probably the actionscript.

So the idea is a gallery with X number of pages with up to 2 images each page and the option of 3 different placements. See here (http://carrionwebdesign.com/forums/fade_up_flash_loading_bar/test.html) for an example (only first 3 pages).

What i've done is make a 40 page template and added 3 empty movie clips and loading bars with the following actionscript:


emptyA.loadMovie("01a.jpg");
loadingBarA._xscale = 1;
loadingBarA.onEnterFrame = function() {
kBytesLoaded = this._parent.emptyA.getBytesLoaded() / 1024;
kBytesTotal = this._parent.emptyA.getBytesTotal() / 1024;
percentage = Math.round(kBytesLoaded / kBytesTotal * 100);
this._xscale = percentage;
if (percentage == 99) {
delete this.onEnterFrame;
}
}
emptyB.loadMovie("01b.jpg");
loadingBarB._xscale = 1;
loadingBarB.onEnterFrame = function() {
kBytesLoaded = this._parent.emptyB.getBytesLoaded() / 1024;
kBytesTotal = this._parent.emptyB.getBytesTotal() / 1024;
percentage = Math.round(kBytesLoaded / kBytesTotal * 100);
this._xscale = percentage;
if (percentage == 99) {
delete this.onEnterFrame;
}
}
emptyC.loadMovie("01c.jpg");
loadingBarC._xscale = 1;
loadingBarC.onEnterFrame = function() {
kBytesLoaded = this._parent.emptyC.getBytesLoaded() / 1024;
kBytesTotal = this._parent.emptyC.getBytesTotal() / 1024;
percentage = Math.round(kBytesLoaded / kBytesTotal * 100);
this._xscale = percentage;
if (percentage == 99) {
delete this.onEnterFrame;
}
}
stop();


The idea is that the client can upload an image and position it by defining the page number and position in it's name eg. 01c.jpg will be 01 (page01) c (far right position).

I found the actionscript on a forum website and it seems to work ok but it's really jerky and no doubt incredibly longwinded. Ideally i'd like it to load evenly each time with a little fade up and down like this (http://www.choppedliver.info/) website.

It would be cool to have each of the 3 loading bars work but if needs be i could always use just one.

Also is there a way of assigning a bit of script? e.g. if image is not found, display blank image (1x1 pix white jpg), this would stop the missing image errors each time you click to the page. Or even better, no load if image not found, thus stopping random loading bar loads then no image.

Massive thanks to anyone who can put me on the right track for this.

Here's the Fla file (http://carrionwebdesign.com/forums/fade_up_flash_loading_bar/test.fla) if that's any help. Please let me know if you need any other info.

Cheers

Gordon

Medyman
10-01-2008, 12:31 PM
Everything that you say is possible. It's not even that hard. Your workflow will be easier. Your code will be more efficient. And your client will have less to do.

But, you'll have to start from scratch. If you're interested, I can walk you through the process. The more efficient, dynamic way is to use a tweening engine for the fading (MC Tween (http://hosted.zeh.com.br/mctween/) is my personal favorite for AS2), the MovieClipLoader class (http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002538.html) for preloading and XML for data entry.

GordonBennett
10-01-2008, 01:07 PM
Thanks Medyman

That would be really helpful, where do you suggest i start? I'll have a browse over the links you just sent.

Thanks again.

Gordon

Medyman
10-01-2008, 05:02 PM
The first is to develop an XML structure that will handle all of the data that you wish to make dynamic. It looks like that date in this case is the source of the image and the position.

So, you might have an XML file such as:


<gallery>
<image src="images/image1.jpg" position="right" />
<image src="image2.jpg" position="center" />
<image src="images/image3.jpg" position="left" />
</gallery

As you can see, it's very intuitive. Your client won't have to mess around with confusing naming conventions. You can make the file paths as flexible as you want them to be. You can have the client fill out the complete path, a relative path, just the filename, or any other combination that you can think of. If you're sure that all the images will reside in the same folder, I suggest using the filename-only approach. The relative path schema with Flash can be kind of confusing. It's best if you leave clients the easiest workflow possible.

You could add as much data to this file as you wanted -- links, descriptions, etc...
Also, this doesn't limit you to 40 pages. The client can add/remove as he pleases.

Set up a sample XML file that fits your data structure, post a snippet, and we'll go from there!

GordonBennett
10-02-2008, 11:05 AM
How would this change if the client wanted two images on one page? example (http://carrionwebdesign.com/forums/fade_up_flash_loading_bar/test.html)...

The idea is that they can replace or reposition the images in the gallery.

I'm using a lightweight cms package (http://cmsfromscratch.com/), is it possible to still use this too?

Here's my code


<?xml version="1.0" encoding="UTF-8"?>
<gallery>
<image src="cms/project1/image01.jpg" position="left" />
<image src="cms/project1/image02.jpg" position="center" />
<image src="cms/project1/image03.jpg" position="left" />
<image src="cms/project1/image04.jpg" position="right" />
<image src="cms/project1/image05.jpg" position="left" />
</gallery>

This is one of a number of swf galleries i'm loading into a flash site will i therefore need to give the gallery a unique name in the xml? e.g.


<gallery1>

Medyman
10-02-2008, 01:13 PM
How would this change if the client wanted two images on one page? example...

The structure is really up to you. The code will be written to pull the correct data from the XML file. So, design the structure that's intuitive to you. You might do something like this:


<gallery>
<page>
<left>path/to/image.jpg</left>
<center>path/to/image.gif</center>
<right></right>
</page>
</gallery>


I'm using a lightweight cms package, is it possible to still use this too?
I'm not familiar with that very product. In general, you can output XML via PHP. So, in theory it would be possible. How exactly it works with that particular software, I have no idea.

If interested, there are better CMS softwares out there that could handle this quite easily and probably require less setup on your part. I specifically am referring to ExpressionEngine (Core).


This is one of a number of swf galleries i'm loading into a flash site will i therefore need to give the gallery a unique name in the xml? e.g.
Again, the structure is entirely up to you. If it's more intuitive for you and your client to use a different/unique name, do so. ActionScript 2 can't read! You can tell it to get the data from particular nodes, but it doesn't care if you call it gallery or elephants. So, the name is really just to make it readable code -- which is also important.

If you wanted to use ActionScript 3, then the naming would be important, as AS3 allows you to reference particular nodes with their tag name.

GordonBennett
10-02-2008, 02:19 PM
Firstly thanks so much for the help. I've read a few intro's to xml+Flash so i'm slowly getting to grips with the idea, nodes etc. Also i've uploaded the files in the xml below.

Ok so my xml file is as follows:


<?xml version="1.0" encoding="UTF-8"?>
<gallery>
<page>
<left>cms/project1/image01.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image02.jpg</left>
<center></center>
<right>cms/project1/image03.jpg</right>
</page>
<page>
<left>cms/project1/image04.jpg</left>
<center></center>
<right>cms/project1/image05.jpg</right>
</page>
<page>
<left>cms/project1/image06.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image07.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image08.jpg</left>
<center></center>
<right>cms/project1/image09.jpg</right>
</page>
<page>
<left>cms/project1/image10.jpg</left>
<center></center>
<right>cms/project1/image11.jpg</right>
</page>
<page>
<left>cms/project1/image12.jpg</left>
<center></center>
<right>cms/project1/image13.jpg</right>
</page>
<page>
<left>cms/project1/image14.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image15.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image16.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image17.jpg</left>
<center></center>
<right>cms/project1/image18.jpg</right>
</page>
<page>
<left>cms/project1/image19.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image20.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image21.jpg</left>
<center></center>
<right></right>
</page>
<page>
<left>cms/project1/image22.jpg</left>
<center></center>
<right>cms/project1/image23.jpg</right>
</page>
<page>
<left>cms/project1/image24.jpg</left>
<center></center>
<right></right>
</page>
</gallery>

Am i right in thinking the Flash will can count the page Nodes and make a total sum for the number of pages, and it will be possible to enter this number into Dynamic text e.g. (15/24).

Thanks again, looking forward to the next step.

Gordon

Medyman
10-02-2008, 03:33 PM
Am i right in thinking the Flash will can count the page Nodes and make a total sum for the number of pages, and it will be possible to enter this number into Dynamic text e.g. (15/24).

Yup.


Thanks again, looking forward to the next step.
I think the next step should be to develop the stage structure. You have two options here:

1) Set up the stage with three empty movieclips -- one each for the positions. If you're just starting with dynamic ActionScript-ing, this might be the easiest to grasp visually.

2) Create one empty movieclip of the size that you want and save it to the library. In this way, you'll maximize efficiency by ensuring that only the assets that are relevant are on the stage at one time. This does take more conceptual understanding of Flash though.

By the way, are you using ActionScript 2.0 or 3.0?

GordonBennett
10-02-2008, 04:25 PM
I'll think i'll go for option 1 as i think i can probably change the original design for the gallery. How much more complicated would option 2 be?

Do i need to give them instance names?

I'm working in Actionscript 2.0.

Medyman
10-02-2008, 04:35 PM
I'll think i'll go for option 1 as i think i can probably change the original design for the gallery. How much more complicated would option 2 be?

It depends on the design. If it's just going to be three empty MCs that images load into, I wouldn't say option 2 is any more complicated than 1. It's just a different way of doing it that's a little bit more conceptual but more efficient as well.

Working with AS 2.0 though, I'd actually recommend going with Option 1.


Do i need to give them instance names?
Yes.

GordonBennett
10-02-2008, 04:49 PM
Ok option 1 it is then. Here (carrionwebdesign.com/forums/fade_up_flash_loading_bar/test.fla) is my updated flash file if you need it.

I've given the three movieclips instances of emptyA_mc emptyB_mc and emptyC_mc. They are in the exact position needed and also i've left in the next/prev buttons and added some dynamic text for the page numbers and also embedded the text.

Medyman
10-02-2008, 06:16 PM
Alright, that's the jist of what I was talking about. The empty movieclips should also be the size of your images. They will resize once you load in the image, but it's easier to visualize and debug if there is something actually there.

Let's trim down the UI that you have to just the basics. You can then take the techniques and apply them toward the specifics of your project.

Here (http://www.mediafire.com/?ecmjdaywyko) is along the lines of what I mean.

Medyman
10-02-2008, 06:18 PM
Also...

If you haven't done so already, you should install MC Tween (http://hosted.zeh.com.br/mctween/). We'll be using it for the fading later on.

GordonBennett
10-03-2008, 09:26 AM
Hey Medyman,

Downloaded test_revised.fla and installed MC Tween (sounds absolutely awesome by the way).

Ready when you are.

Gordon

Medyman
10-03-2008, 01:49 PM
Alright, let's get the XML up and running. ALl of the ActionScript that I refer to should be added to frame 1 of the "Actions" panel. You'll only have 1 frame in this entire application. Everything will be done at runtime.

So, to initiate the XML object:

var xml:XML = new XML();
xml.ignoreWhite = true;

xml.onLoad = function(success) {
if(success) {
trace("XML Loaded");
}
else {
trace("Error: XML Didn't Load");
}
}

xml.load("test.xml");

The above code loads the XML (called test.xml for example's sake) file. If successful, it'll trace "XML Loaded" and if there's a problem, it'll trace out an error message.

Next, let's add some relevance to this. We'll add a variable that holds the total number of "pages" and set it's value via the onLoad() function. We have to declare the variable outside the function so that it's scope extends to the rest of the code.

We'll also create a function called loadImages(). Like it sounds, it'll load the images. The code should now look something like this:

// Initiate XML
var xml:XML = new XML();
xml.ignoreWhite = true;

// Variables
var total:Number = new Number();

// Load XML
xml.onLoad = function(success) {
if(success) {
total = xml.firstChild.childNodes.length // Set total number of pages
loadImages();
}
else {
trace("Error: XML Didn't Load");
}
}

// Load Images
function loadImages() {
// Here is where most of the code goes
}

xml.load("test.xml");

I haven't explicitly explained the code. You seem confident enough with AS to understand the code thus far. Let me know if you have other questions.

The next step is to set up some more variables, and write the loadImages() function.

GordonBennett
10-03-2008, 02:28 PM
Brilliant!

Ok i've added the actionscript to the actions layer1. I've tested the movie and no errors occur.

Thanks, i'm mostly following you so far and reading up on the rest as i go.

Medyman
10-03-2008, 04:07 PM
Alright, so let's get some images in.

First, let's make a small change to the XML to make it a bit more flexible and easier to update. It seems like all of your images are in the same directory. If this is the case, then follow the steps below.

I've added an attribute to the <gallery> node called path. This will contain the directory path to the images. My images are in the images/ directory, so I have something like this:


<gallery path="images/">
<page>
<left>1.jpg</left>
<center>2.jpg</center>
<right>3.jpg</right>
</page>
...

Now, let's add a variable in Flash to store this information.

First, initiate the variable:

// Variables
var total:Number = new Number();
var path:String = new String();

Then, set the value within the xml.onLoad() loop:

// Load XML
xml.onLoad = function(success) {
if(success) {
total = xml.firstChild.childNodes.length // Set total number of pages
path = xml.firstChild.attributes.path;
loadImages();
}
else {
trace("Error: XML Didn't Load");
}
}

Next, we'll need to set up an array to hold the names of the three "picture frames". This will allow us to use easier coding techniques to refer to each of these movieclips. We could refer to each by name directly, but that would require repetitive code. If I want all three to behave the same way, it's much easier to assign the property to each at the same time.

So, lets create the array. We'll call it positions.

// Variables
var total:Number = new Number();
var path:String = new String();
var positions:Array = new Array(left, center, right);

Now, we get to the good stuff. Let's create the loadImages() function. In order to reuse the function, we'll add pass a paramater -- the page number. This will allow us to target particular nodes within the XML.

Here is the code. I'll explain it below.

// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!="") {
positions[i].loadMovie(imagePath);
}
}
}

First, note that I'm passing in a parameter (page) into the function. Second, one thing to always keep in mind is that Flash counts starting with 0. So, the first element in an array is at index 0, not 1. The first node in the XML is at index 0, not 1.

The very first thing I do in the function is display the page number. The parameter (page) isn't technically the page number. At least, not in human readable format. It's the index of the node. So, to make it human readable, we need to add one.

Next, we have a for loop. Since there are three positions (and three corresponding nodes in the XML), I'm looping through the XML three times. If you need more info on for loops, let me know. So bascially, I'm reading the value of each child node of the <page> node within the loop. The first time, it reads the first node (<left>), the second time it reads <center> and so on...

I then take whatever value that is and set it equal to a variable -- imagePath. Note that I'm concatenating the path variable from earlier to this value so we get the full path to the image. If the variable isn't blank, I load the image into the appropriate movieclip.

This is where the array comes in. The element in the array and the node of the XML have the same index. Node 0 of the XML (<left>) can then be linked with the movieclip left (which is at index 0 in the array) through the same "variable" (i in this case).

Hopefully that's not too confusing. If you have any questions, please ask. Putting it all together, your AS should not look something like this:

// Initiate XML
var xml:XML = new XML();
xml.ignoreWhite = true;

// Variables
var total:Number = new Number();
var path:String = new String();
var positions:Array = new Array(left, center, right);

// Load XML
xml.onLoad = function(success) {
if(success) {
total = xml.firstChild.childNodes.length // Set total number of pages
path = xml.firstChild.attributes.path;
loadImages(0);
}
else {
trace("Error: XML Didn't Load");
}
}

// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!="") {
positions[i].loadMovie(imagePath);
}
}
}

xml.load("test.xml");

You should now be loading the images from the first set of images in the XML.
Next, we'll add the navigation (next and previous buttons).

GordonBennett
10-03-2008, 06:22 PM
I can't thank you enough, this must be taking you ages to do!

Ok so i've tested the movie and it comes back with an "Error opening URL" where the image "undefined".

I'm starting to see how flexile the xml can be written, i've been reading the livedocs.adobe.com pages for the actionscript and they're a real help in explaining what isn't familiar. I'm beginning to understand the language...

I'll keep familiarizing myself with the code you've sent and wait for the next installment.

Thanks again.

Gordon

Medyman
10-03-2008, 07:15 PM
Is the URL error with the XML file or the images? That error simply means that there is an error in the path. I don't know what your file structure is, but the image paths in the XML file should be relative to the Flash file.

You might try tracing out the imagePath variable to see what's it's calling up.

GordonBennett
10-03-2008, 07:43 PM
Ok don't know what happened there but it's fine now.

Thanks, what's next?

Medyman
10-03-2008, 08:55 PM
Alright, great.

Next...the next/previous buttons.

First, in order to manipulate the page number, we'll have to add it to a variable. I'm going to call it current for current page and set it equal to 0 at the beginning of the movie. Remember that the page number is really the XML index (which starts at 0). Have I said that enough? :-p


// Variables
var total:Number = new Number();
var path:String = new String();
var positions:Array = new Array(left, center, right);
var current:Number = 0;

To reflect this change, we'll update our onLoad() function from loadImages(0) to loadImages(current).


// Load XML
xml.onLoad = function(success) {
if(success) {
total = xml.firstChild.childNodes.length // Set total number of pages
path = xml.firstChild.attributes.path;
loadImages(current);
}
else {
trace("Error: XML Didn't Load");
}
}

Now, we're ready to write the logic for the next/previous buttons. First, the next. Each time we click the next button we want the page to go up one. In other words, we want current to increase by one. Then, we want to load the images associated with that next page.

So, we do something like this:

function goForward() {
current++;
loadImages(current);
}

current++ increases current by one each time the function is called. Since we made loadImages() flexible by adding the parameter, we can easily call the images associated with the next "page".

The same logic applies with the previous function. This time, we're just decreasing current by one.

function goBackward() {
current--;
loadImages(current);
}

Next, we assign those functions on the onRelease states of the next and previous buttons.

next.onRelease = goForward;
prev.onRelease = goBackward;

To wrap up, let's add some logic to test for when the next and previous buttons are needed. On the first page, we don't need the previous button. On the last page, we don't need the next button. So let's create a function that tests for those conditions.

function createNavigation() {
// Show/Hide Next Button
if(current >= (total-1)) {
next._visible = false;
}
else {
next._visible = true;
}

// Show/Hide Prev Button
if(current == 0) {
prev._visible = false;
}
else {
prev._visible = true;
}
}

We'll want to call this function each time the page is changed. The one function we 100% know will get called on each page is loadImages(). So, we'll add a function call to createNavigation() within loadImages() right after the for loop.


function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!="") {
positions[i].loadMovie(imagePath);
}
}
createNavigation();
}

That's it. Now, you should have working navigation. The pages should change accordingly. The page number display should update accordingly. Let me know if that doesn't happen.

All together, this is the AS I have so far:

// Initiate XML
var xml:XML = new XML();
xml.ignoreWhite = true;

// Variables
var total:Number = new Number();
var path:String = new String();
var positions:Array = new Array(left, center, right);
var current:Number = 0;

// Load XML
xml.onLoad = function(success) {
if(success) {
total = xml.firstChild.childNodes.length // Set total number of pages
path = xml.firstChild.attributes.path;
loadImages(current);
}
else {
trace("Error: XML Didn't Load");
}
}

// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!="") {
positions[i].loadMovie(imagePath);
}
}
createNavigation();
}

// Next Button
next.onRelease = goForward;
function goForward() {
current++;
loadImages(current);
}

// Previous Button
prev.onRelease = goBackward;
function goBackward() {
current--;
loadImages(current);
}

// Create Navigation
function createNavigation() {
// Show/Hide Next Button
if(current >= (total-1)) {
next._visible = false;
}
else {
next._visible = true;
}

// Show/Hide Prev Button
if(current == 0) {
prev._visible = false;
}
else {
prev._visible = true;
}
}

xml.load("test.xml");

Next, we'll use the MovieClipLoader class to load in the images and create a preloader. Lee Brimelow has a great video tutorial on gotoAndLearn() (http://www.gotoandlearn.com) about this, if you're interested. It's entitled "External SWF Preloading".

GordonBennett
10-04-2008, 03:28 PM
That's amazing! I just looked at my original .fla file and actionscript, it's amazing how streamlined you've made it. All working perfectly, great! I'm very excited.

I might have a go at changing the hiding buttons so that the gallery continuously rotates through and i'm wondering if it's possible for the page number to always have 2 digits e.g. 01/20 instead of 1/20. If i get stuck i might have to ask some advice if that's cool?

I had a quick look at the video's, i'll definitely bookmark them. I've got to go for a wedding reception tonight and it's my birthday tomorrow so i won't have a chance to look at the code properly until monday.

Thanks so much for helping.

Gordon

Medyman
10-04-2008, 04:13 PM
i'm wondering if it's possible for the page number to always have 2 digits e.g. 01/20 instead of 1/20
Sure...
The page number is being set here:

pageNo.text = "PAGE " + (page+1) + " OF " + total;
You'll need to provide some logic to test to see if "page" is less than 10 and then add the leading 0 manually.


If i get stuck i might have to ask some advice if that's cool?
Yeah, of course. You're still a bit away from my limit of questions in one thread, lol.


I've got to go for a wedding reception tonight and it's my birthday tomorrow so i won't have a chance to look at the code properly until monday.
Just post back when you're ready to move forward. I'll probably add the next bit of code later today. Oh, and happy B-day.

Enjoy the weekend.

GordonBennett
10-06-2008, 03:39 PM
Thanks Medyman.

Superb. I've adapted it to my own design now and it looks great. Having a time trying to figure out where and how to change the script to keep the buttons visible and scrolling through the images and logic for the 0 for pages lower than 10. Any hints?

Thanks again

Gordon

Medyman
10-07-2008, 04:16 PM
By "scrolling" through the images, do you mean that you want them to change (i.e. progress forward) automatically. If so, you want to use setInterval() (http://www.adobe.com/support/flash/action_scripts/actionscript_dictionary/actionscript_dictionary646.html).

The function you call with that would be very similar to goForward() (from my example code). You would need to insert a conditional statement that tests if "current" is equal to "total". If so, reset "current" to 0.

As for the page number, this would be one way of doing it. It's a bit verbose, but illustrates the point.

if(current < 10) {
pageNo.text = "PAGE 0" + (page+1) + " OF " + total;
}
else {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
}

If you plan to having less than 10 items total, you'll need to run this kind of logic against the "total" variable as well.

GordonBennett
10-07-2008, 04:30 PM
Thanks for the code, i've been trying out some things today and evidently i'm on the track.

By scrolling forward i mean; once the gallery has come to the last image and you click next button i wanted the gallery to go back to the first image and the same for the first page and the previous button, basically a looped gallery. Is this terribly complicated?

Medyman
10-07-2008, 11:22 PM
Is this terribly complicated?
Nope. That's actually simpler than what I was imagining. We already have the skeleton for the code in our goForward() and goBackward() functions. We just need to add a small check in there.


function goForward() {
current++;
if(current >= total) { current = 0; }
loadImages(current);
}


function goBackward() {
current--;
if(current <= 0) { current = (total-1); }
loadImages(current);
}

You would also want to get rid of the createNavigation() function.

GordonBennett
10-08-2008, 09:02 AM
Ahhhhh! I was so close...I think i just missed out "loadImages(current);" off the end, damn and blast!

Thanks though, the preceding zero issue has also been resolved.

This is really coming together now, where do we go from here?

Very excited, thanks Medyman

Medyman
10-09-2008, 01:05 PM
Alright, next lets use the MovieClipLoader class to load in the images. We're currently using loadMovie() to do this. loadMovie() is a global Function for doing practically the same general thing as the MovieClipLoader class. However, the MCL class also includes some additional methods that allow us to "preload" our external assets (the images in this case).

First, for aesthetic reasons, let's make some changes to the interface. Open up any one of the "image" movieclips (instance names left, right, center). Double click on the rectangle make sure you do not select the stroke, left click, and select "Distribute to Layers". Next, create a new layer and copy and paste the rectangle that you just distributed. Now, you should have three layers -- one with just the stroke and two with rectangles. Turn both of the rectangles into separate movieclips. Give one an instance name of "loading" and the other an instance name of "holder". The holder movieclip will hold our image and the loading movieclip will display a loading message. Make sure the layers are in this order (from top-down) -- first, the layer w/ the stroke, then "loading", then "holding". If you would like, you can add whatever loading message you want within "loading". Here (http://www.mediafire.com/file/nkldzqzmiyj/test_revised_2.fla) is what I'm working with.

Now, that we have that done, let's get to some code! The only thing we'll be changing is our loadImages() function (for obvious reasons). The code is pretty standard MCL class stuff. You haven't watched the video I recommended before (link (http://gotoandlearn.com/play?id=27)), you'll want to do that for a better understanding of what's going on.


// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!="") {
var loader:MovieClipLoader = new MovieClipLoader();
var listener:Object = new Object();

listener.onLoadInit = function(target) {
target._parent.loading._visible = false;
}

loader.addListener(listener);
loader.loadClip(imagePath,positions[i].holder);
}
}
}

You might not see the change when testing locally. You obviously don't need to preload anything that you're pulling off of your hard drive. So, in order to test it properly you'll want to "Simulate Download". When you test the movie, go into the View menu and select the appropriate option. You can change what speed the simulation uses in the "Download Settings" menu. I prefer to test at DSL speed.

As always, let me know if you have any questions. The next step will be adding some fading action. If you want, you can familiarize yourself a bit with MC Tween before we begin.

GordonBennett
10-09-2008, 03:27 PM
Thanks Medyman

The preloading animation is working fine for the first page but is missing each time you advance to each subsequent page. I've even checked it with your template and the same thing is happening. I'm not sure is it's just because these loose ends will be tied up with the next bit of coding or not. Also as you'll see from my xml file, the maximum number of images i'll load in will be 2, sometimes 1 if it's in landscape orientation. Is there a way to hide any unused loading movieclips? Something like...if node is empty hide movieclip?

Here (http://carrionwebdesign.com/forums/fade_up_flash_loading_bar/GALLERY_TEMPLATE.fla) is my flash file and here (http://carrionwebdesign.com/forums/fade_up_flash_loading_bar/test.xml) is my xml file.

I'm also getting 1 url error each time i advance, "images/" is this because we're using a path? I've tried with different paths and images but it still comes up.

Thanks again for all your help, i'll look at those links in the meantime.

Cheers Again.

Medyman
10-09-2008, 06:58 PM
The preloading animation is working fine for the first page but is missing each time you advance to each subsequent page. I've even checked it with your template and the same thing is happening. I'm not sure is it's just because these loose ends will be tied up with the next bit of coding or not.
Loose ends, as you say. Recalling and dispersing the loading message has more to do with the fading. So, I've left that off as yet. We'll cover it when we go over using MC Tween.


Also as you'll see from my xml file, the maximum number of images i'll load in will be 2, sometimes 1 if it's in landscape orientation. Is there a way to hide any unused loading movieclips? Something like...if node is empty hide movieclip?
Sure, it's possible. We're already testing to see if the node is empty (well, we're testing to see if it's NOT empty, but same thing) and running a conditional based off of that. So, you can just add an else statement to it. I'll cover it in my next installment.


I'm also getting 1 url error each time i advance, "images/" is this because we're using a path? I've tried with different paths and images but it still comes up.
Yeah, "images" represents the path to the images. If all of your files are in the same folder ("images" in this case), then it's much easier to declare the path once at the top of the XML, then simply add the filename to the rest of the XML. Your XML has path="images/. So, the path to your images (relative to the .fla) should be images/filename.jpg. In your previous examples you posted a path of cms/project1/filename.jpg. If that's still your directory structure, replace images/ with cms/project1/. Remember, the path is FROM the .fla file.

Let me know when you have this path thing sorted out and we'll move on to the animations.

Medyman
10-09-2008, 07:20 PM
I see what you mean now about the path thing. I didn't quite understand you before. I was testing with each node filled, so I didn't notice the mistaken logic. The culprit is in these two lines:

var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!='') {

We're setting imagePath equal to the value of the node plus the path variable. Then in the conditional, we're testing to see if imagePath is blank. That'll never be true (unless something is wrong with the path variable). So, let's fix that. Change it to:

var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!=path) {

Hopefully that fixes your URL errors. Confirm that it does and we'll move on.

GordonBennett
10-10-2008, 09:00 AM
Sweet! Worked a treat. Thanks Medyman.

Reviewing the MC Tween now and ready to move on.

Gordon

Medyman
10-14-2008, 10:54 PM
Hey Gordon...
Sorry for not posting for a few days. Had some personal things to deal with. Anyway, let's get back with this.

To refresh: We currently have an XML powered "slideshow" that loads up to 3 images per page and then adds pagination functionality.

Now we're looking to add some visual interest and tie up some loose ends. As mentioned before, we'll be using MC Tween to perform all the tweening. There are other tweening engines out there -- including Flash's native Tween class -- but I'm most fond of MC Tween for use with AS 2.

First, we "include" MC Tween so we can access its methods:

// Import MC Tween
#include "mc_tween2.as"

Next, let's animate the "loading" message. Currently, we have it being set to be invisible within the onLoadInit() method call. Using MC Tween, let's fade the "loading" message out.

listener.onLoadInit = function(target) {
target._parent.loading.alphaTo(0, .75, "easeOutQuad");
}
This uses an alpha tween to go from loading's current alpha state to 0% alpha transparency over .75 seconds using an "easeOutQuad" animation type. Go over the MC Tween documentation for more about animation/ease types.

Ok, so now it fades. Like you mentioned before, this only happens the first time. That is because once it's tweened, it's alpha is at 0. Therefore, there is no need to tween it again. So, we should reset the alpha transparency before we tween it.

// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
positions[i].loading.alphaTo(100, .75, "easeOutQuad");
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!=path) {
var loader:MovieClipLoader = new MovieClipLoader();
var listener:Object = new Object();

listener.onLoadInit = function(target) {
target._parent.loading.alphaTo(0, .75, "easeOutQuad");
}

loader.addListener(listener);
loader.loadClip(imagePath,positions[i].holder);
}
}
}
Alright, great! Now we have the "loading" message showing where there is no image to be loaded. Instead of showing that, let's fade out that particular "frame". We have a conditional that tests to see if an image is to be loaded within a frame. We can utilize that to set an "else" conditional in case the "frame" is empty.

// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
positions[i].loading.alphaTo(100, .75, "easeOutQuad");
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!=path) {
var loader:MovieClipLoader = new MovieClipLoader();
var listener:Object = new Object();

listener.onLoadInit = function(target) {
target._parent.loading.alphaTo(0, .75, "easeOutQuad");
}

loader.addListener(listener);
loader.loadClip(imagePath,positions[i].holder);
}
else {
positions[i].alphaTo(0, .5, "easeOutQuad");
}
}
}
Now test and you'll find that once a "frame" is faded out, it stays that way. Again, we need to reset the alpha of the positions[i] movieclip.

// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
positions[i].loading.alphaTo(100, .75, "easeOutQuad");
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!=path) {
positions[i].alphaTo(100, .5, "easeOutQuad");
var loader:MovieClipLoader = new MovieClipLoader();
var listener:Object = new Object();

listener.onLoadInit = function(target) {
target._parent.loading.alphaTo(0, .75, "easeOutQuad");
}

loader.addListener(listener);
loader.loadClip(imagePath,positions[i].holder);
}
else {
positions[i].alphaTo(0, .5, "easeOutQuad");
}
}
}

There you have it. You should now have the fade-in/out that you were looking for. Post back with any questions.

Medyman
10-14-2008, 10:55 PM
For reference, below is the AS that I have:

// Import MC Tween
#include "mc_tween2.as"

// Initiate XML
var xml:XML = new XML();
xml.ignoreWhite = true;

// Variables
var total:Number = new Number();
var path:String = new String();
var positions:Array = new Array(left, center, right);
var current:Number = 0;

// Load XML
xml.onLoad = function(success) {
if(success) {
total = xml.firstChild.childNodes.length // Set total number of pages
path = xml.firstChild.attributes.path;
loadImages(current);
}
else {
trace("Error: XML Didn't Load");
}
}

// Load Images
function loadImages(page) {
pageNo.text = "PAGE " + (page+1) + " OF " + total;
for(i=0;i<3;i++) {
positions[i].loading.alphaTo(100, .75, "easeOutQuad");
var imagePath:String = path + xml.firstChild.childNodes[page].childNodes[i].childNodes
if(imagePath!=path) {
positions[i].alphaTo(100, .5, "easeOutQuad");
var loader:MovieClipLoader = new MovieClipLoader();
var listener:Object = new Object();

listener.onLoadInit = function(target) {
target._parent.loading.alphaTo(0, .75, "easeOutQuad");
}

loader.addListener(listener);
loader.loadClip(imagePath,positions[i].holder);
}
else {
positions[i].alphaTo(0, .5, "easeOutQuad");
}
}
}

// Next Button
next.onRelease = goForward;
function goForward() {
current++;
if(current >= total) { current = 0; }
loadImages(current);
}

// Previous Button
prev.onRelease = goBackward;
function goBackward() {
current--;
if(current <= 0) { current = (total-1); }
loadImages(current);
}

xml.load("test.xml");

GordonBennett
10-15-2008, 05:04 PM
That's absolutely fantastic! Exactly how i imagined it to work. I can't thank you enough Medyman, you've certainly shown me the flexibility and full potential of Flash and actionscript!

A million thank you's.

Gordon

Medyman
10-15-2008, 10:44 PM
You're very welcome. I'm glad I could help.