Skip to content


Actionscript 3 Carousel Animation for Menu

So, after reviewing the Carousel videos from gotoandlearn.com, I revised the code and adapted it for Actionscript 3 for a new project that I will be working on. Here is a demo.. for now the only type of control of the carousel is the left and right direction, won’t stop for now.

Here is the Document class:

package
{
	import flash.display.Sprite;
	import flash.display.MovieClip;

	// for the xml file
	import flash.net.URLLoader;
	import flash.net.URLRequest;

	// events
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;

	import flash.display.Loader;
    import flash.display.LoaderInfo;

	// graphics
	import flash.filters.BlurFilter;

	public class Main extends Sprite
	{

		private var xml:XML;
		private var ba:Array = new Array(); // Bottle Array
		private var ct:Number = 0; // just a counter

		private var numOfItems:Number = 3;
		private var radiusX:Number = 275;
		private var radiusY:Number = -10;
		private var centerX:Number = (stage.stageWidth / 2) - 70; // the -70 is an offset because of the image size
		private var centerY:Number = (stage.stageHeight / 2) - 240; // the - 240 is an offset because of the image size
		private var speed:Number = 0.04;
		private var perspective:Number = 120;
		private var angle:Number;

		private var imgLoader:Loader;

		public function Main()
		{
			loadXML();

		}

		private function loadXML():void
		{
			var loader:URLLoader = new URLLoader();
			loader.load(new URLRequest("http://manewc.com/projects/flash/Carousel/icons.xml"));
			loader.addEventListener(Event.COMPLETE, loadBottles);
		}

		private function loadBottles(e:Event):void
		{
			// pull in the xml file and load the song data
			xml = new XML(e.target.data);

			var imglist:XMLList = xml.bottleimages.@image;

			for each (var urlXML:XML in imglist)
			{

				angle = ct * ((Math.PI*2)/numOfItems);

				ba.push(new Bottle(imglist[ct],angle));

				// Load in the image
            	imgLoader = new Loader();
            	imgLoader.load(new URLRequest(ba[ct].earl));

				// add to stage
				addChild(ba[ct]);

				// add image loader to the new mc
				ba[ct].addChild(imgLoader);

				ct++;
			}

			if ( ba.length == 0 )
			{
				trace("\nloadSongs Function - no XML data provided");
			}
			else
			{
				// xml is loaded
				trace("\nxml is loaded - " + ba);

				// animate
				addEventListener(Event.ENTER_FRAME, mover);

				// capture mouse events
				stage.addEventListener(MouseEvent.MOUSE_MOVE, adjustSpeed);
			}
		}

		private function imageLoaded(e:Event):void
		{
			addChild(imgLoader);
		}

		private function mover(e:Event):void
		{
			for ( var b=0; b < ba.length; b++ )
			{
				// xpos
				ba[b].x = Math.cos(ba[b].bottleAngle) * radiusX + centerX;

				// ypos
				ba[b].y = Math.sin(ba[b].bottleAngle) * radiusY + centerY;

				// perspective
				var s = (ba[b].y - perspective) /(centerY+radiusY-perspective);
				ba[b].scaleX = ba[b].scaleY = s;

				// update
				ba[b].bottleAngle+= speed;
			}

			// rearrange
			sortZ();
		}

		private function sortZ():void
		{
			ba.sortOn("scaleX"); // re arrange by X scale in ascending order, by default

			for(var i:uint = 0; i < numOfItems; i++)
			{
				setChildIndex(ba[i], i);
			}
		}

		private function adjustSpeed(m:MouseEvent):void
		{
			speed = (mouseX-centerX)/2500;
		}
	}
}

Here is class that is the object for when reading the xml file:

package
{
	import flash.display.MovieClip;
	import flash.display.Loader;
    import flash.display.LoaderInfo;  

	public class Bottle extends MovieClip
	{
		// public properties for the class
		public var earl:String;
		public var bottleAngle:Number;

		public var imgLoader:Loader = new Loader();

		public function Bottle(e:String,a:Number)
		{
			earl = e;
			bottleAngle = a;
		}
	}
}

the xml file:

<icons>
<bottleimages image="http://manewc.com/projects/flash/Carousel/i/sport.png" />
<bottleimages image="http://manewc.com/projects/flash/Carousel/i/original-lemonlime.png" />
<bottleimages image="http://manewc.com/projects/flash/Carousel/i/infused-blackraspberry.png" />
</icons>

Posted in Actionscript 3, Actionscript XML.


21 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. dk says

    ….missing shadows.

    I “optimized” your code a bit, and I added in some neat features. Send me an email if you want to take a look at the code.

    -Dk

  2. Webshop-Winkelen says

    I can’t understand that you made your code so dependend on your implementation and thus not very re-usable.

    Anyway, thank you very much as it helped me a lot getting started coding a carousel.

  3. Kosa says

    Please dk, show us your optimized code and a preview! Thanks!

  4. Seb says

    Hello ,

    I’m developing a 3d carousel.
    Would be very interested in having a look at your maended code.

    Can you please send it to me ?

    Thanks

  5. sofie says

    I made a 3d carousel as well.
    Can you make the carousel stop already?
    I like some help, because it loops over my other scenes.

    Thanks

  6. admin says

    Hi Sofie, To make the carousel stop, you will need to remove the event listener for the mover function:

    removeEventListener(Event.ENTER_FRAME, mover);

    -Morgan

  7. Nigel Dean says

    Hi.

    First time looking at this kind of thing, but I’m looking to redesign my site and wanted a carousel to show customers the various products we have in different catagories.

    Is it possible to produce a carousel of 4 – 6 products and when they hit the front view (0 degrees in the 360 degree turn) a load of text appears below which gives details on that product! i.e no click to a seperate page to see that info… it all appears as the product hits the front and then disapears when the product moves past…. and the next product and text appears….

    ANY help on if this is possible and how easy it may be would be great.

    Cheers

    Nigel.

  8. admin says

    Hi Nigel,

    To have the products display some text you could write a function that detects what their z-index is on, from there you could display their respective content.

    Thanks, Morgan

  9. drk says

    Sorry about the delay, but I was way too busy with school. ^_^ anyways, here’s the code that I promised.

    import com.leebrimelow.ui.Objects;
    import caurina.transitions.Tweener;

    var xml:XML;
    var objectArray:Array = new Array(); // Object Array
    var mirrorArray:Array = new Array();
    var ct:Number = 0; // just a counter

    var numOfItems:Number = 6; //Number of Items

    var percentLoaded:Number = 0;
    var radiusX:Number = 200; //Creates the invisible Ellipse track where the items will rotate.
    var radiusY:Number = 20;

    var centerX:Number = (stage.stageWidth / 2); // the -70 is an offset because of the image size
    var centerY:Number = (stage.stageHeight / 2);// the – 240 is an offset because of the image size

    var speed:Number = 0; //Initial Speed
    var perspective:Number = 120; //Perspective degree in which the “camera” will be looking from.
    var angle:Number; //Angle

    var button:Sprite;
    var imgLoader:Loader; //Image Loader;
    var mirrorLoader:Loader;
    var originalImage:Sprite;
    var mirrorImage:Sprite;
    var rect:Sprite; //rectangle
    var matrix:Matrix = new Matrix();

    var imageWidth:Number = 191; //Size properties of the Image.
    var imageHeight:Number = 156;

    loadXML();

    function loadXML():void
    {
    stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;

    var loader:URLLoader = new URLLoader();
    loader.load(new URLRequest(”icons.xml”));

    //Events
    percent.autoSize = TextFieldAutoSize.LEFT;
    percent.textColor = 0×000000;
    percent.text = ” 0%”;
    percent.x = stage.stageWidth/2 – percent.width;
    percent.y = stage.stageHeight/2 – percent.height;
    addChild(percent);

    loader.addEventListener(Event.COMPLETE, loadObjects);
    }

    //
    //Load all objects, in this case load all of the carousel icons whose address is
    //
    function loadObjects(e:Event):void
    {
    // pull in the xml file and load the song data
    xml = new XML(e.target.data);

    var imglist:XMLList = xml.bottleimages.@image;

    for each (var urlXML:XML in imglist)
    {
    angle = ct * ((Math.PI*2)/numOfItems);

    objectArray.push(new Objects(imglist[ct],angle));
    mirrorArray.push(new Objects(imglist[ct],angle));

    ///*/*/*/*/*/*/*/* Image Loader */*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
    imgLoader = new Loader(); //Initialize Loader
    imgLoader.load(new URLRequest(objectArray[ct].url)); // Load URL;
    imgLoader.x = 0;
    imgLoader.y = 0;
    imgLoader.scaleX = imgLoader.scaleY = .5;

    //*/*/*/*/*/*/*/* Mirror Loader */*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
    mirrorLoader = new Loader(); //Initialize mirrorLoader
    mirrorLoader.load(new URLRequest(mirrorArray[ct].url)); //Load image;
    mirrorLoader.rotation = -180;
    mirrorLoader.x = imageWidth * .5 ; // should be y, since it’s rotated 180 degrees, mirror effect
    trace(”imgLoader.width ” + imgLoader.width);
    mirrorLoader.y = (imageHeight * .5) * 2 + 10;
    mirrorLoader.scaleX = mirrorLoader.scaleY = .5;
    mirrorLoader.alpha = .5;
    //*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

    originalImage = new Sprite();
    mirrorImage = new Sprite();
    originalImage.addChild(imgLoader);
    mirrorImage.addChild(mirrorLoader);

    button = new Sprite();
    button.addChild(originalImage);
    button.addChild(mirrorImage);
    originalImage.buttonMode = true;

    addChild(objectArray[ct]);

    // add image loader to the new mc
    objectArray[ct].addChild(/*imgLoader*/button);

    originalImage.addEventListener(MouseEvent.ROLL_OVER, onMouseOver);
    originalImage.addEventListener(MouseEvent.ROLL_OUT, onMouseOut);
    originalImage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

    ct++;
    }

    if ( objectArray.length == 0 )
    {
    trace(”\nloadSongs Function – no XML data provided”);
    }
    else
    {
    // xml is loaded
    trace(”\nxml is loaded – ” + objectArray);

    // animate
    addEventListener(Event.ENTER_FRAME, mover);

    // capture mouse events
    stage.addEventListener(MouseEvent.MOUSE_MOVE, adjustSpeed);
    }
    }

    function onMouseDown(e:MouseEvent):void
    {
    //Place your logic here
    trace(e.currentTarget + ” MouseDown”);
    e.currentTarget.scaleX = 1;
    e.currentTarget.scaleY = 1;
    Tweener.addTween( this, { alpha: 0, onComplete: thisMove, time: .5});
    speed = 0;

    }

    function thisMove():void
    {
    this.x = 1000;
    }

    function onMouseOver(e:MouseEvent):void
    {
    if(e.currentTarget.scaleX <= 1)
    {
    Tweener.addTween( e.currentTarget, { scaleX: e.currentTarget.scaleX * 1.5, scaleY: e.currentTarget.scaleY * 1.5 , time: .7});
    }
    trace(e.currentTarget.scaleX);
    }

    function onMouseOut(e:MouseEvent):void
    {
    Tweener.addTween( e.currentTarget, { scaleX: 1, scaleY: 1, time: .5});

    }

    function imageLoaded(e:Event):void
    {
    addChild(imgLoader);
    }

    function mover(e:Event):void
    {

    for ( var b=0; b < objectArray.length; b++ )
    {
    // xpos
    objectArray[b].x = Math.cos(objectArray[b].objectAngle) * radiusX + centerX ;

    // ypos
    objectArray[b].y = Math.sin(objectArray[b].objectAngle) * radiusY + centerY;

    // perspective
    var s = (objectArray[b].y – perspective) /(centerY+radiusY-perspective);
    objectArray[b].scaleX = objectArray[b].scaleY = s;

    // update
    objectArray[b].objectAngle+= speed;
    }

    // rearrange
    sortZ();
    }

    function sortZ():void
    {
    objectArray.sortOn(”scaleX”); // re arrange by X scale in ascending order, by default
    for(var i:uint = 0; i < numOfItems; i++)
    {
    setChildIndex(objectArray[i], i);
    }
    }

    function adjustSpeed(m:MouseEvent):void
    {
    speed = (mouseX-centerX – 50)/1500;
    }

    This was placed on a fla file where the carousel was being held on a movieclip whose actionscript code was on the first frame.

  10. drk says

    Object.as
    package com.ui.Carousel.Objects;
    {
    import flash.display.MovieClip;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormatAlign;

    public class Objects extends MovieClip
    {
    // public properties for the class
    public var url:String;
    public var objectAngle:Number;

    //Metadata
    public var bLoaded:Number = 0;
    public var bTotal:Number = 0;
    public var percent:TextField = new TextField();

    public var imgLoader:Loader = new Loader();

    public function Objects(url:String,a:Number)
    {
    this.url = url;
    objectAngle = a;
    }
    }
    }

  11. Max says

    Hi,
    can you put this in a working package for download please?

  12. worked says

    What if I just wanted Text instead of Images? What would I need to change in order to load up textFields? Thanks!

  13. Andre Dickson says

    Thanks so much for posting this. I was really getting worried about how to sort Z depth and your solution is great.

  14. Francis says

    Dude – it took me a while to figure out exactly why you were creating another object – I see now. A hell of a lot of trouble to go through just to swap depths. Nice work though – good solution.

  15. Suzan says

    hi,

    is it possible when you click a bottle, it will move to the center of stage, and the bottles stay in proper position? So you can select a bottle in the back, and the carrousel moves to it’s correct position?

    i think it has to do something with the sort Z function? Can’t get it to work. Hope somebody can help me out. thx

  16. Jitendra says

    Hi,
    Can you please tell me how to stop the animation if I use caurina function addTween(). I didn’t understand how to stop the my image slideshow.

    Hope somebody can help me.
    Thanks

  17. Phil says

    Hi,

    is there any possibility to use this code with Flex 3?

    Thx for your answer

  18. sandrar says

    Hi! I was surfing and found your blog post… nice! I love your blog. :) Cheers! Sandra. R.

  19. daidddai says

    thanks for this example

  20. Agustin says

    Thanks, I my self embarked on the gotoAndLearn AS2 carousel to AS3 carousel boat with no success… what had me troubled was the z-sorting which you handled very straight forwardly.
    I don’t think your code lacks optimisation, it’s just a little too rigid, but How rigid can four functions be?

    Thanks a lot.

Continuing the Discussion

  1. Optimized XML-based AS3 Carousel « timshaya linked to this post on September 9, 2009

    [...] XML-based AS3 Carousel Here’s a quick way to optimize this AS3 carousel-style image gallery / [...]



Some HTML is OK

or, reply to this post via trackback.