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>
….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
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.
Please dk, show us your optimized code and a preview! Thanks!
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
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
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
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.
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
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.
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;
}
}
}
Hi,
can you put this in a working package for download please?
What if I just wanted Text instead of Images? What would I need to change in order to load up textFields? Thanks!
Thanks so much for posting this. I was really getting worried about how to sort Z depth and your solution is great.
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.
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
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
Hi,
is there any possibility to use this code with Flex 3?
Thx for your answer
Hi! I was surfing and found your blog post… nice! I love your blog.
Cheers! Sandra. R.
thanks for this example
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.