Skip to main content
Goshine
Inspiring
November 25, 2009
Question

Load images in the correct order, needs help..

  • November 25, 2009
  • 3 replies
  • 1549 views

I have tried loading in some images in the order of the xml files.. that contain them ..

they did load in one by one but .. in  random order .. so mabe i am doing too much or too liitle can some one give it asecond look for me ..

//-- load Xml
urlLoader.load(new URLRequest("loader_alpabet/loader_alpabet.xml"));
urlLoader.addEventListener(Event.COMPLETE,xmlReady);
this.addEventListener(Event.ENTER_FRAME,entFrm);
// process the Xml and create array of objs
function xmlReady(evt:Event):void {
     xml=new XML(evt.target.data);
     var xmlListUrls:XMLList=new XMLList(xml.image.url.text());
     var xmlListNames:XMLList=new XMLList(xml.image.name.text());
     var xmlListDescs:XMLList=new XMLList(xml.image.description.text());
     for (var g:Number = 0; g < xmlListNames.length(); g++) {
          imagePack.push({name:xmlListNames,url:xmlListUrls,desc:xmlListDescs});
       
          if (xmlListUrls.length()==imagePack.length) {
               loaderMachine();
          }
     }

}

//this is where i position the images
function entFrm(evt:Event):void {
     if (imageIcons.length>0) {
          for (var g:Number = 0; g < imageIcons.length; g++) {
               imageIcons.x=(centerX+Math.cos(angle+g)*radiusX)-imageIcons.width/2;
               imageIcons.y=(centerY+Math.sin(angle+g)*radiusY)-imageIcons.height/2;
               imageIcons.scaleX=imageIcons.scaleY= ((imageIcons.y/150) - 0.5);
               stage.addChildAt(imageIcons, imageIcons.scaleX);
               angle+=speed;
          }
     }
}

//-- loader function
function loaderMachine():void {
     trace(imagePack.length);

     loader = new Loader();
     loader.load(new URLRequest(imagePack[count].url));
     loader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageReady);

}
// put image on stage
function imageReady(evt:Event):void {
     var image:Bitmap = (Bitmap)(evt.target.content);
     addChild(image);
     imageIcons.push(image);
     count++;
     if (count<imagePack.length) {
          loaderMachine();


     }


}
This topic has been closed for replies.

3 replies

Muzak
Inspiring
November 25, 2009

If you want to load them in the order provided in the xml file, you'll have to load them one at a time, rather than all at once (in a loop).

The randomness of the images loading when using a loop is because each image has a different filesize, so smaller images load faster than larger ones (DUH) and loading external assets is asynchronous.

In short, no matter how hard you try, if you load them in a loop, they'll never come in the order you want.

So basically you'll need to:

- use a counter variable to keep track of how many images are already loaded (initially 0)

- load first image (counter = 0)

- when loaded load next image and increase counter (counter += 1)

- repeat till all images are loaded (counter == array length-1)

November 25, 2009

He's not loading them in a loop... and he's already using a counter.

Anyway...

You are still not exiting the loop properly and you are still adding child on your enter frame loop. Fix those two things and then see if it is working.

Muzak
Inspiring
November 25, 2009

ah, I missed the 2nd version of the code

You have to take the loaderMachine(); call out of the loop, call it after the loop.

function xmlReady(evt:Event):void {
     xml=new XML(evt.currentTarget.data);
     var xmlListUrls:XMLList=new XMLList(xml.image.url.text());
     var xmlListNames:XMLList=new XMLList(xml.image.name.text());

     var xmlListDescs:XMLList=new XMLList(xml.image.description.text());
     for (var g:Number = 0; g < xmlListNames.length(); g++) {
          imagePack.push({name:xmlListNames,url:xmlListUrls,desc:xmlListDescs});
     }
      // start loading images

     loaderMachine();
}

You're overwriting you loader instance each time you load an image, that's not good if you want it to stick around (display each loaded image).

So in the method, create a local Loader instance and add it to the Array stack.

Don't start the enterFrame event handler until all images are loaded.

You can do so in the imageReady() event handler (check if counter equals array length).

Don't add event listeners in the enterFrame event handler, you're adding them over and over again.

So remove these from entFrm()

 imageIcons.addEventListener(MouseEvent.MOUSE_OVER,btn_mouse);
imageIcons.addEventListener(MouseEvent.MOUSE_OUT,btn_mouse);

Don't use Event.target (unless you know what you're doing), use currentTarget instead.

function imageReady(evt:Event):void {
     var loader:Loader = (event.currentTarget as LoaderInfo).loader;

     loader.addEventListener(MouseEvent.MOUSE_OVER, btn_mouse);

     loader.addEventListener(MouseEvent.MOUSE_OUT, btn_mouse);

     addChild((loader);
     count++;
     if (count<imagePack.length) {
          loaderMachine();
    }else{

          addEventListener(Event.ENTERFRAME, entFrm);

    }}

Don't use Array.length in a loop condition, as this will check the lenght with each iteration, slowing down the loop.

Set it to a local variable once and use that as the loop condition.

var len:uint = imageIcons.length;

for(var i:uint=0; i<len; i++) {}

Last but not least, you're probably better off using a tween engine rather than an enterFrame event to move things around.

Look into TweenLite.

http://blog.greensock.com/tweenlite/

It now looks like the enterFrame event continues untill you roll over one of the buttons? If so, that can't be good..

function loaderMachine():void {
     var loader:Loader = new Loader();
     loader.load(new URLRequest(imagePack[count].url));
     loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageReady);
     imageIcons.push(loader);
}

November 25, 2009

I don't much like how you're calling loaderMachine() from inside the for loop. If you're worried about the list of url's being shorter than the other data, and are calling loaderMachine when you're at the end of the url's you can't guarantee the urls match the names. If you're just exiting the loop at the end, then you should use xmlListUrls.length() in the test to exit the loop and not be ambiguous.

for (var g:Number = 0; g < xmlListUrls.length(); g++) {
          imagePack.push({name:xmlListNames,url:xmlListUrls,desc:xmlListDescs});
}
loaderMachine();
       

Call loaderMachine when the loop is complete... not when it's potentially still running.

Next you have:

stage.addChildAt(imageIcons, imageIcons.scaleX);

Inside of an enterFrame handler... you are adding bitmaps over and over? The other elements do not get removed, they just get bumped up the display list. I think you just want to remove that line.That is what's causing you to think they are loading out of order, since you're positioning them based on the length of the array, which changes each time a new image loads...

Goshine
GoshineAuthor
Inspiring
November 25, 2009

this is the ful code i have made some changes

now all the images are loading in the right order but as soon as i push them in the

circle they are gone mad ....

i have put the xml live on my domain so if you run the script  you should see what i me

var urlLoader:URLLoader = new URLLoader();
var loader:Loader;
var xml:XML;
var imagePack:Array  = new Array();
var imageIcons:Array  = new Array();
var counter:Number=0;
var angle:Number=0;
var centerY:Number=stage.stageHeight/2;
var centerX:Number=stage.stageWidth/2;
var speed:Number=0.001;
var radiusX:Number=180;
var radiusY:Number=90;
var count:Number=0;

//-- loade Xml
urlLoader.load(new URLRequest("http://www.goshine-design.co.uk/loader_alpabet/loader_alpabet.xml"));
urlLoader.addEventListener(Event.COMPLETE,xmlReady);
this.addEventListener(Event.ENTER_FRAME,entFrm);
// process the Xml and create array of objs
function xmlReady(evt:Event):void {
     xml=new XML(evt.target.data);
     var xmlListUrls:XMLList=new XMLList(xml.image.url.text());
     var xmlListNames:XMLList=new XMLList(xml.image.name.text());
     var xmlListDescs:XMLList=new XMLList(xml.image.description.text());
     for (var g:Number = 0; g < xmlListNames.length(); g++) {
          imagePack.push({name:xmlListNames,url:xmlListUrls,desc:xmlListDescs});
          //imagePack.reverse();
          if (xmlListUrls.length()==imagePack.length) {
               loaderMachine();
          }
     }

}

//this is where i position the images
function entFrm(evt:Event):void {
     if (imageIcons.length==imagePack.length) {
          if (imageIcons.length>0) {
               for (var g:Number = 0; g < imageIcons.length; g++) {
                    imageIcons.x=(centerX+Math.cos(angle+g)*radiusX)-imageIcons.width/2;
                    imageIcons.y=(centerY+Math.sin(angle+g)*radiusY)-imageIcons.height/2;
                    imageIcons.scaleX=imageIcons.scaleY= ((imageIcons.y/150) - 0.5);
                    imageIcons.addEventListener(MouseEvent.MOUSE_OVER,btn_mouse);
                    imageIcons.addEventListener(MouseEvent.MOUSE_OUT,btn_mouse);
                    addChild(imageIcons);

                    angle+= (((mouseX) - stage.stageWidth/2) /100000);
                    
               }
          }
     }
}
//--- button activity


function btn_mouse(e:MouseEvent):void {


     if (e.type=="mouseOver") {
          this.removeEventListener(Event.ENTER_FRAME,entFrm);
          e.target.y -= 10
     } else if (e.type =="mouseOut" ) {
          e.target.alpha=1;
          this.addEventListener(Event.ENTER_FRAME,entFrm);
     }

}
//-- loader function
function loaderMachine():void {
     loader = new Loader();
     loader.load(new URLRequest(imagePack[count].url));
     loader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageReady);

}
// put image on stage
function imageReady(evt:Event):void {
     
     addChild((evt.target).loader);
     imageIcons.push((evt.target).loader);
     count++;
     if (count<imagePack.length) {
          loaderMachine();


     }


}

Ned Murphy
Legend
November 25, 2009

I don't think having your image placement function working off of an enterframe event is a good idea.  What you should do is have your placement for each individual image performed in (or via a call from) the imageReady function.  Rather than having a for loop managing the g value and the placement (which I believe will be continuously arranging all of the images, even after they have all been loaded since I don't see that event listener being removed), just declare g as a variable and increment it in the imageREady function as each image gets placed.  I see you have a count variable that is not being used, and that is what you would need for what you use the g value for.