There are several great AS3 / Papervision Coverflows out there but today I set out to create one in it’s simplest form. There are no bells and whistles, just a stripped down coverflow with it’s core functionality. It’s up to you to add an XML feed, Flickr feed, or setup your images in an array and load them the way you want to. This is only meant to be a clean jumping off point.
In the download I have included 2 versions. One with left / right buttons and one without. Both versions you can select the items in the coverflow to navigate.
The heart of this coverflow app is a lot like some of the others. We need to calculate the x and rotation of the center item, left items, and right items are, then animate accordingly. This is the same way that John Dyer animates his coverflow.
for (var i:int = 0; i < planes.length; i++) { var plane:Plane = planes[i]; //Each if statement will adjust these numbers as needed var planeX:Number = 0; var planeZ:Number = 20; var planeRotationY:Number = 0 //Place & Animate Center Item if (i == currentItem) { planeZ = -300 TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } ); } //Place & Animate Right Items if(i > currentItem) { planeX = (i - currentItem + 1) * 120; planeRotationY = angle + 10 * (i - currentItem); TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } ); } //Place & Animate Left Items if (i < currentItem) { planeX = (currentItem - i + 1) * -120; planeRotationY = -angle - 10 * (currentItem - i); TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } ); } } |
For this simple version of coverflow you have two ways of navigating to items.
Selecting a plane to jump right to that item
plane.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, onPlaneClick); protected function onPlaneClick(evt:InteractiveScene3DEvent):void { currentItem = evt.target.id; animate(); } |
Or using left / right buttons to navigate one item at a time:
rightBtn.addEventListener(MouseEvent.CLICK, buttonClick); leftBtn.addEventListener(MouseEvent.CLICK, buttonClick); protected function buttonClick(evt:MouseEvent):void { switch (evt.target) { case rightBtn: currentItem ++ break; case leftBtn: currentItem --; break; } //Don't allow any number lower than 0 or past max so there //is always a center item if (currentItem < 0) { currentItem = 0; } if (currentItem > (planes.length - 1)) { currentItem = planes.length - 1; } //Call animation animate(); } |
On to the full source code. This version includes the left / right buttons.
package { import flash.display.DisplayObject; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.filters.GlowFilter; import gs.easing.Quint; import gs.TweenLite; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.materials.BitmapFileMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Plane; import org.papervision3d.view.BasicView; /** * ... * @author Charlie Schulze, charlie[at]woveninteractive[dot]com * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php */ public class Main extends BasicView { protected var planes:Array = []; protected var numItems:Number = 7; protected var currentItem:Number = 3; protected var angle:Number = 25; protected var mat:BitmapFileMaterial; protected var rightBtn:Sprite; protected var leftBtn:Sprite; public function Main():void { //Make sure that your scene is set to interactive super(640, 480, true, true); init(); } protected function init():void { createChildren(); createNavigation(); animate(); startRendering(); } protected function createChildren():void { //Create Material mat = new BitmapFileMaterial("images/iPhone-back2.png"); mat.smooth = true; mat.interactive = true; for (var i:int = 0; i < numItems; i++) { var plane:Plane = new Plane(mat, 177, 334, 4, 4); planes.push(plane); //Click straight to any plane plane.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, onPlaneClick); //Set an id to target current item plane.id = i; //Add plane to the scene scene.addChild(plane); } camera.zoom = 60; } protected function onPlaneClick(evt:InteractiveScene3DEvent):void { currentItem = evt.target.id; animate(); } //Animate the coverflow left / right based off of currentItems protected function animate():void { for (var i:int = 0; i < planes.length; i++) { var plane:Plane = planes[i]; //Each if statement will adjust these numbers as needed var planeX:Number = 0; var planeZ:Number = -50; var planeRotationY:Number = 0 //Place & Animate Center Item if (i == currentItem) { planeZ = -300 TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } ); } //Place & Animate Right Items if(i > currentItem) { planeX = (i - currentItem + 1) * 120; planeRotationY = angle + 10 * (i - currentItem); TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } ); } //Place & Animate Left Items if (i < currentItem) { planeX = (currentItem - i + 1) * -120; planeRotationY = -angle - 10 * (currentItem - i); TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } ); } } } /* * Everything below this point is just for creating the buttons and * setting button events for controlling the coverflow. */ protected function createNavigation():void { //Create / Add Buttons rightBtn = createButton(); leftBtn = createButton(); addChild(leftBtn); addChild(rightBtn); //Add button listeners rightBtn.buttonMode = true; leftBtn.buttonMode = true; rightBtn.addEventListener(MouseEvent.CLICK, buttonClick); leftBtn.addEventListener(MouseEvent.CLICK, buttonClick); //Place buttons on stage rightBtn.x = stage.stageWidth - 20; leftBtn.x = 20; rightBtn.y = stage.stageHeight / 2; leftBtn.y = (stage.stageHeight / 2) + 20; leftBtn.rotation = 180; } //Button actions protected function buttonClick(evt:MouseEvent):void { switch (evt.target) { case rightBtn: currentItem ++ break; case leftBtn: currentItem --; break; } //Don't allow any number lower than 0 or past max so there //is always a center item if (currentItem < 0) { currentItem = 0; } if (currentItem > (planes.length - 1)) { currentItem = planes.length - 1; } //Call animation animate(); } //Creates a simple arrow shape / returns the sprite protected function createButton():Sprite { var btn:Sprite = new Sprite(); btn.graphics.beginFill(0x333333); btn.graphics.moveTo(0, 0); btn.graphics.lineTo(0, 20); btn.graphics.lineTo(10, 10); btn.graphics.lineTo(0, 0); btn.graphics.endFill(); btn.filters = [new GlowFilter(0xFFFFFF,1,10,10,3)] return btn; } } } |
That’s it. This should provide a good base for you to build out your own unique coverflow.

Nice tutorial but how do I reposition the Coverflow?
For example my flash has a button and some text that needs to go underneath, but I can’t work out how to move the Coverflow Y location up.
Help :)
thanks, great tutorial!
When I use large size pictures, it shows a z-sorting problem. I tried to find out the solution but couldn’t.
Hi,
great tutorial, thx.
How can i add a mirror reflect of all the planes??
Pingback: Anonymous
Thanks for the tutorial! I’ve been looking around for a good coverflow script that was straightforward enough for me to customize and to actually understand what it was doing–and this was it! I added some tweaks using mod (%) to make an endless/circular coverflow with an autoplay function. Though for some reason the onPlaneClick function stopped working when I put movieclips in the image planes instead of bitmaps… so still working out a few kinks. But you can see how it’s looking here: A Fresh Web Design
Pingback: A Simple Away3D Coverflow | Flash 3D
Pingback: Ryan Liu | Flash ActionScript
Hey this is a great tutorial. Any idea how you could integrate a scroll bar into this? I’d like to work with this script as its only one file unlike all the other tutorials I’ve found.