help with as3 image carousel

  • goltoof
  • Newbie
  • Newbie
  • goltoof
  • Posts: 7

Post 3+ Months Ago

I got this script for an xml controlled image carousel. It works really well, I just need to tweak it a bit to get it to work the way I want.

I want to position the carousel in a certain area of the movie. The only parameter that I see to control where it's positioned is "var floor:Number = 20;" but this only controls the vertical position. I need to control the horizontal position, right now it's just centered. I see "xpos3D" but don't know what to make of it.

I also want to keep it from showing up outside of the frames I want it to appear. Right now when I put the script in the movie it shows up in every frame. How do I get it appear only in certain frames of the movie? When i put "stop();" at the end of the keyframe it still shows in the frames after it.

The last thing I need is to position the animation on top of other layers. Right now it appears below all other layers in the movie.

I don't know what parts to modify to accomplish this so of course I don't know what parts to post, which is why I'm posting the whole thing.

Hints on how to accomplish any of the above much appreciated! :)


Code: [ Select ]
//We use 70x70 sized images (change this if different for your images)
const IMAGE_WIDTH:uint = 70;
const IMAGE_HEIGHT:uint = 70;

//Set the focal length
var focalLength:Number = 400;

//Set the vanishing point
var vanishingPointX:Number = stage.stageWidth / 2;
var vanishingPointY:Number = stage.stageHeight / 2;

//The 3D floor for the images
var floor:Number = 20;

//We calculate the angleSpeed in the ENTER_FRAME listener
var angleSpeed:Number = 0;

//Radius of the circle
var radius:Number = 200;

//Specify the path to the XML file.
//You can use my path or your own.
var xmlFilePath:String = "3D-carousel-settings.xml";

//We save the loaded XML to a variable
var xml:XML;

//This array will contain all the imageHolders
var imageHolders:Array = new Array();

//We want to know how many images have been loaded
var numberOfLoadedImages:uint = 0;

//The total number of images according to XML file
var numberOfImages:uint = 0;

//Load the XML file.
var loader = new URLLoader();
loader.load(new URLRequest(xmlFilePath));

//We call the function xmlLoaded() when the loading is complete.
loader.addEventListener(Event.COMPLETE, xmlLoaded);

//This function is called when the XML file is loaded
function xmlLoaded(e:Event):void {

    //Create a new XML object from the loaded XML data
    xml = new XML(loader.data);
    xml.ignoreWhitespace = true;

    //Call the function that loads the images
    loadImages();
}

//This function loads and creates holders for the images specified in the 3D-carousel-settings.xml
function loadImages():void {

    //Get the total number of images from the XML file
    numberOfImages = xml.number_of_images;

    //Loop through the images found in the XML file
    for each (var image:XML in xml.images.image) {

        //Create a new image holder for an image
        var imageHolder:MovieClip = new MovieClip();

        //Create a loader that will load an image
        var imageLoader = new Loader();

        //Add the imageLoader to the imageHolder
        imageHolder.addChild(imageLoader);

        //We don't want to catch any mouse events from the loader
        imageHolder.mouseChildren = false;

        //Position the imageLoader so that the registration point of the holder is centered
        imageLoader.x = - (IMAGE_WIDTH / 2);
        imageLoader.y = - (IMAGE_HEIGHT / 2);

        //Save where the imageHolder should link to
        imageHolder.linkTo = image.link_to;

        //Add the imageHolder to the imageHolders array
        imageHolders.push(imageHolder);

        //Load the image
        imageLoader.load(new URLRequest(image.url));

        //Listen when the image is loaded
        imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
    }
}

//This function is called when an image is loaded
function imageLoaded(e:Event):void {

    //Update the number of loaded images
    numberOfLoadedImages++;

    //Set the bitmap smoothing to true for the image (we know that the loader's content is a bitmap).
    e.target.content.smoothing = true;

    //Check to see if this is the last image loaded
    if (numberOfLoadedImages == numberOfImages) {

        //Set up the carousel
        initializeCarousel();
    }
}

//This function is called when all the images have been loaded.
//Now we are ready to create the 3D carousel.
function initializeCarousel():void {

    //Calculate the angle difference between the images (in radians)
    var angleDifference:Number = Math.PI * (360 / numberOfImages) / 180;

    //Loop through the images
    for (var i:uint = 0; i < imageHolders.length; i++) {

        //Assign the imageHolder to a local variable
        var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);

        //Get the angle for the image (we space the images evenly)
        var startingAngle:Number = angleDifference * i;

        //Position the imageHolder
        imageHolder.xpos3D = radius * Math.cos(startingAngle);
        imageHolder.zpos3D = radius * Math.sin(startingAngle);
        imageHolder.ypos3D = floor;

        //Set a "currentAngle" attribute for the imageHolder
        imageHolder.currentAngle = startingAngle;

        //Calculate the scale ratio for the imageHolder (the further the image -> the smaller the scale)
        var scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);

        //Scale the imageHolder according to the scale ratio
        imageHolder.scaleX = imageHolder.scaleY = scaleRatio;

        //Set the alpha for the imageHolder
        imageHolder.alpha = 0.3;

        //We want to know when the mouse is over and out of the imageHolder
        imageHolder.addEventListener(MouseEvent.MOUSE_OVER, mouseOverImage);
        imageHolder.addEventListener(MouseEvent.MOUSE_OUT, mouseOutImage);

        //We also want to listen for the clicks
        imageHolder.addEventListener(MouseEvent.CLICK, imageClicked);

        //Position the imageHolder to the stage (from 3D to 2D coordinates)
        imageHolder.x = vanishingPointX + imageHolder.xpos3D * scaleRatio;
        imageHolder.y = vanishingPointY + imageHolder.ypos3D * scaleRatio;

        //Add the imageHolder to the stage
        addChild(imageHolder);
    }

    //Add an ENTER_FRAME for the rotation
    addEventListener(Event.ENTER_FRAME, rotateCarousel);
}

function rotateCarousel(e:Event):void {

    //Calculate the angleSpeed according to mouse position
    angleSpeed = (mouseX - vanishingPointX) / 4096;

    //Loop through the images
    for (var i:uint = 0; i < imageHolders.length; i++) {

        //Assign the imageHolder to a local variable
        var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);

        //Update the imageHolder's current angle
        imageHolder.currentAngle += angleSpeed;

        //Set a new 3D position for the imageHolder
        imageHolder.xpos3D=radius*Math.cos(imageHolder.currentAngle);
        imageHolder.zpos3D=radius*Math.sin(imageHolder.currentAngle);

        //Calculate a scale ratio
        var scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);

        //Scale the imageHolder according to the scale ratio
        imageHolder.scaleX=imageHolder.scaleY=scaleRatio;

        //Update the imageHolder's coordinates
        imageHolder.x=vanishingPointX+imageHolder.xpos3D*scaleRatio;
        imageHolder.y=vanishingPointY+imageHolder.ypos3D*scaleRatio;
    }

    //Call the function that sorts the images so they overlap each others correctly
    sortZ();
}

//This function sorts the images so they overlap each others correctly
function sortZ():void {

    //Sort the array so that the image which has the highest
    //z position (= furthest away) is first in the array
    imageHolders.sortOn("zpos3D", Array.NUMERIC | Array.DESCENDING);

    //Set new child indexes for the images
    for (var i:uint = 0; i < imageHolders.length; i++) {
        setChildIndex(imageHolders[i], i);
    }
}

//This function is called when the mouse is over an imageHolder
function mouseOverImage(e:Event):void {

    //Set alpha to 1
    e.target.alpha=1;
}

//This function is called when the mouse is out of an imageHolder
function mouseOutImage(e:Event):void {

    //Set alpha to 0.3
    e.target.alpha=0.3;
}

//This function is called when an imageHolder is clicked
function imageClicked(e:Event):void {

    //Navigate to the URL that is in the "linkTo" variable
    navigateToURL(new URLRequest(e.target.linkTo));
}
  1. //We use 70x70 sized images (change this if different for your images)
  2. const IMAGE_WIDTH:uint = 70;
  3. const IMAGE_HEIGHT:uint = 70;
  4. //Set the focal length
  5. var focalLength:Number = 400;
  6. //Set the vanishing point
  7. var vanishingPointX:Number = stage.stageWidth / 2;
  8. var vanishingPointY:Number = stage.stageHeight / 2;
  9. //The 3D floor for the images
  10. var floor:Number = 20;
  11. //We calculate the angleSpeed in the ENTER_FRAME listener
  12. var angleSpeed:Number = 0;
  13. //Radius of the circle
  14. var radius:Number = 200;
  15. //Specify the path to the XML file.
  16. //You can use my path or your own.
  17. var xmlFilePath:String = "3D-carousel-settings.xml";
  18. //We save the loaded XML to a variable
  19. var xml:XML;
  20. //This array will contain all the imageHolders
  21. var imageHolders:Array = new Array();
  22. //We want to know how many images have been loaded
  23. var numberOfLoadedImages:uint = 0;
  24. //The total number of images according to XML file
  25. var numberOfImages:uint = 0;
  26. //Load the XML file.
  27. var loader = new URLLoader();
  28. loader.load(new URLRequest(xmlFilePath));
  29. //We call the function xmlLoaded() when the loading is complete.
  30. loader.addEventListener(Event.COMPLETE, xmlLoaded);
  31. //This function is called when the XML file is loaded
  32. function xmlLoaded(e:Event):void {
  33.     //Create a new XML object from the loaded XML data
  34.     xml = new XML(loader.data);
  35.     xml.ignoreWhitespace = true;
  36.     //Call the function that loads the images
  37.     loadImages();
  38. }
  39. //This function loads and creates holders for the images specified in the 3D-carousel-settings.xml
  40. function loadImages():void {
  41.     //Get the total number of images from the XML file
  42.     numberOfImages = xml.number_of_images;
  43.     //Loop through the images found in the XML file
  44.     for each (var image:XML in xml.images.image) {
  45.         //Create a new image holder for an image
  46.         var imageHolder:MovieClip = new MovieClip();
  47.         //Create a loader that will load an image
  48.         var imageLoader = new Loader();
  49.         //Add the imageLoader to the imageHolder
  50.         imageHolder.addChild(imageLoader);
  51.         //We don't want to catch any mouse events from the loader
  52.         imageHolder.mouseChildren = false;
  53.         //Position the imageLoader so that the registration point of the holder is centered
  54.         imageLoader.x = - (IMAGE_WIDTH / 2);
  55.         imageLoader.y = - (IMAGE_HEIGHT / 2);
  56.         //Save where the imageHolder should link to
  57.         imageHolder.linkTo = image.link_to;
  58.         //Add the imageHolder to the imageHolders array
  59.         imageHolders.push(imageHolder);
  60.         //Load the image
  61.         imageLoader.load(new URLRequest(image.url));
  62.         //Listen when the image is loaded
  63.         imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
  64.     }
  65. }
  66. //This function is called when an image is loaded
  67. function imageLoaded(e:Event):void {
  68.     //Update the number of loaded images
  69.     numberOfLoadedImages++;
  70.     //Set the bitmap smoothing to true for the image (we know that the loader's content is a bitmap).
  71.     e.target.content.smoothing = true;
  72.     //Check to see if this is the last image loaded
  73.     if (numberOfLoadedImages == numberOfImages) {
  74.         //Set up the carousel
  75.         initializeCarousel();
  76.     }
  77. }
  78. //This function is called when all the images have been loaded.
  79. //Now we are ready to create the 3D carousel.
  80. function initializeCarousel():void {
  81.     //Calculate the angle difference between the images (in radians)
  82.     var angleDifference:Number = Math.PI * (360 / numberOfImages) / 180;
  83.     //Loop through the images
  84.     for (var i:uint = 0; i < imageHolders.length; i++) {
  85.         //Assign the imageHolder to a local variable
  86.         var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
  87.         //Get the angle for the image (we space the images evenly)
  88.         var startingAngle:Number = angleDifference * i;
  89.         //Position the imageHolder
  90.         imageHolder.xpos3D = radius * Math.cos(startingAngle);
  91.         imageHolder.zpos3D = radius * Math.sin(startingAngle);
  92.         imageHolder.ypos3D = floor;
  93.         //Set a "currentAngle" attribute for the imageHolder
  94.         imageHolder.currentAngle = startingAngle;
  95.         //Calculate the scale ratio for the imageHolder (the further the image -> the smaller the scale)
  96.         var scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
  97.         //Scale the imageHolder according to the scale ratio
  98.         imageHolder.scaleX = imageHolder.scaleY = scaleRatio;
  99.         //Set the alpha for the imageHolder
  100.         imageHolder.alpha = 0.3;
  101.         //We want to know when the mouse is over and out of the imageHolder
  102.         imageHolder.addEventListener(MouseEvent.MOUSE_OVER, mouseOverImage);
  103.         imageHolder.addEventListener(MouseEvent.MOUSE_OUT, mouseOutImage);
  104.         //We also want to listen for the clicks
  105.         imageHolder.addEventListener(MouseEvent.CLICK, imageClicked);
  106.         //Position the imageHolder to the stage (from 3D to 2D coordinates)
  107.         imageHolder.x = vanishingPointX + imageHolder.xpos3D * scaleRatio;
  108.         imageHolder.y = vanishingPointY + imageHolder.ypos3D * scaleRatio;
  109.         //Add the imageHolder to the stage
  110.         addChild(imageHolder);
  111.     }
  112.     //Add an ENTER_FRAME for the rotation
  113.     addEventListener(Event.ENTER_FRAME, rotateCarousel);
  114. }
  115. function rotateCarousel(e:Event):void {
  116.     //Calculate the angleSpeed according to mouse position
  117.     angleSpeed = (mouseX - vanishingPointX) / 4096;
  118.     //Loop through the images
  119.     for (var i:uint = 0; i < imageHolders.length; i++) {
  120.         //Assign the imageHolder to a local variable
  121.         var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
  122.         //Update the imageHolder's current angle
  123.         imageHolder.currentAngle += angleSpeed;
  124.         //Set a new 3D position for the imageHolder
  125.         imageHolder.xpos3D=radius*Math.cos(imageHolder.currentAngle);
  126.         imageHolder.zpos3D=radius*Math.sin(imageHolder.currentAngle);
  127.         //Calculate a scale ratio
  128.         var scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
  129.         //Scale the imageHolder according to the scale ratio
  130.         imageHolder.scaleX=imageHolder.scaleY=scaleRatio;
  131.         //Update the imageHolder's coordinates
  132.         imageHolder.x=vanishingPointX+imageHolder.xpos3D*scaleRatio;
  133.         imageHolder.y=vanishingPointY+imageHolder.ypos3D*scaleRatio;
  134.     }
  135.     //Call the function that sorts the images so they overlap each others correctly
  136.     sortZ();
  137. }
  138. //This function sorts the images so they overlap each others correctly
  139. function sortZ():void {
  140.     //Sort the array so that the image which has the highest
  141.     //z position (= furthest away) is first in the array
  142.     imageHolders.sortOn("zpos3D", Array.NUMERIC | Array.DESCENDING);
  143.     //Set new child indexes for the images
  144.     for (var i:uint = 0; i < imageHolders.length; i++) {
  145.         setChildIndex(imageHolders[i], i);
  146.     }
  147. }
  148. //This function is called when the mouse is over an imageHolder
  149. function mouseOverImage(e:Event):void {
  150.     //Set alpha to 1
  151.     e.target.alpha=1;
  152. }
  153. //This function is called when the mouse is out of an imageHolder
  154. function mouseOutImage(e:Event):void {
  155.     //Set alpha to 0.3
  156.     e.target.alpha=0.3;
  157. }
  158. //This function is called when an imageHolder is clicked
  159. function imageClicked(e:Event):void {
  160.     //Navigate to the URL that is in the "linkTo" variable
  161.     navigateToURL(new URLRequest(e.target.linkTo));
  162. }
  • Anonymous
  • Bot
  • No Avatar
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post 3+ Months Ago

  • graphixboy
  • Control + Z
  • Mastermind
  • User avatar
  • Posts: 1828
  • Loc: In the Great White North

Post 3+ Months Ago

Create an empty movieclip on the stage in the frame you want to use. Then put all your carousel code INSIDE that blank clip. That way you should be able to position it wherever you want and it shouldn't show on multiple frames.
  • goltoof
  • Newbie
  • Newbie
  • goltoof
  • Posts: 7

Post 3+ Months Ago

graphixboy wrote:
Create an empty movieclip on the stage in the frame you want to use. Then put all your carousel code INSIDE that blank clip. That way you should be able to position it wherever you want and it shouldn't show on multiple frames.


Thanks. That makes it seem crazy easy. I created the blank clip, dragged it to the stage, gave it an instance name. In CS4 I can't just put the carousel code "in" the blank clip. So I put the code in the layer where the clip is (I assume this is wrong but it's the only option I see), the carousel is still behind everything and shows up on every frame. I put the code in the frame when I double click the clip, the carousel is still behind everything, but in a different position and doesn't show on every frame.. What am I missing?

In either case, the blank clip shows on the stage as a tiny dot. I need to resize it and reposition it. Changing the properties for x/y position does nothing and h/w properties are grayed out.
  • graphixboy
  • Control + Z
  • Mastermind
  • User avatar
  • Posts: 1828
  • Loc: In the Great White North

Post 3+ Months Ago

well a blank clip doesn't have a height or width since it doesn't have any content until the script runs so you won't be able to modify that. I assume the script is telling the carousel around the center point of the given parent which was the stage before but is now the little "dot" of the empty movie clip. If you move that little dot to the location you want the carousel to center it should work.

As for being below everything, your basically telling flash to draw the carousel inside the blank clip so you should be able to simply move the blank clip to a higher layer.
  • goltoof
  • Newbie
  • Newbie
  • goltoof
  • Posts: 7

Post 3+ Months Ago

graphixboy wrote:
As for being below everything, your basically telling flash to draw the carousel inside the blank clip so you should be able to simply move the blank clip to a higher layer.


I moved the movie clip dot around and got it positioned where I want without it showing on every frame. Score! :D

The problem still remains that the carousel shows behind everything, even though the layer containing it is positioned above every other layer.

Is this addressed in the code?
  • graphixboy
  • Control + Z
  • Mastermind
  • User avatar
  • Posts: 1828
  • Loc: In the Great White North

Post 3+ Months Ago

hmm the code is now on the timeline INSIDE the blank movie clip correct?

If so try changing line 156 from your code above to this.addChild(imageHolder);

I think its still trying to attach the images to the main stage even though it should be inside that clip. If the "this" doesn't work you might want to try blankclipinstancename.addChild(imageHolder);
  • goltoof
  • Newbie
  • Newbie
  • goltoof
  • Posts: 7

Post 3+ Months Ago

Nevermind!!! It's working just the way I want it! I thought it'd be neat to see how to accomplish all this with AS but if you don't need to know sometimes it's better not to.

Thanks!
  • graphixboy
  • Control + Z
  • Mastermind
  • User avatar
  • Posts: 1828
  • Loc: In the Great White North

Post 3+ Months Ago

Glad it worked. You could have done it all with the code but I've found that when your trying to integrate someone elses work into your project the method you followed is usually best.
  • goltoof
  • Newbie
  • Newbie
  • goltoof
  • Posts: 7

Post 3+ Months Ago

There is one little problem that arises. I have the carousel positioned on the right side of the billboard, not the center. So the right perimeter of the carousel is just on the border of the swf (20px margin), whereas there is 700px or so to the left perimeter of the carousel

The speed of the carousel is dependent on the position of the mouse. When the mouse hovers to the right of the carousel the speed reaches a peak and stays there as the mouse moves off the swf. But when the mouse hovers to the opposite end of the billboard, the carousel gradually spins ridiculously fast. I'd like to make it balanced so the carousel reaches the same speed on both sides and stops seeing mouseover at a certain point on the left.

Does this make sense?

Do you see a place to address this in the code? Otherwise I assume there's some kind of wrapper I can apply around the empty movie clip that keeps the mouseover effect contained?
  • goltoof
  • Newbie
  • Newbie
  • goltoof
  • Posts: 7

Post 3+ Months Ago

I got it looking the way I need, but this speed bug is pretty major and makes it for the most part unusable. I see the "angleSpeed = (mouseX - vanishingPointX) / 4096;" which as is only controls the mouseover speed, but I'm quite clueless how to fix this bug from here.

I'll keep looking but any hints much appreciated.

Post Information

  • Total Posts in this topic: 10 posts
  • Users browsing this forum: No registered users and 4 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.