As a simple addition to yesterday's coverflow post, I wanted to show the same example but with loading images via XML. For simplicity sake the XML is loaded and parsed all in the main file.
The structure for our XML is very simple:
-
<?xml version="1.0" encoding="utf-8" ?>
-
<data>
-
<image><![CDATA[images/image1.jpg]]></image>
-
<image><![CDATA[images/image2.jpg]]></image>
-
<image><![CDATA[images/image3.jpg]]></image>
-
<image><![CDATA[images/image5.jpg]]></image>
-
<image><![CDATA[images/image4.jpg]]></image>
-
<image><![CDATA[images/image6.jpg]]></image>
-
<image><![CDATA[images/image7.jpg]]></image>
-
</data>
We simply load our XML file with BulkLoader
-
protected function loadXML():void
-
{
-
bulkInstance = new BulkLoader("bulkInstance");
-
bulkInstance.add(xmlPath);
-
bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
-
bulkInstance.start();
-
}
Parse the results, now adding the images to the BulkLoader:
-
protected function onXMLReady(evt:BulkProgressEvent):void
-
{
-
bulkInstance.removeEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
-
bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onImagesReady);
-
-
var xml:XML = bulkInstance.getXML(xmlPath);
-
var xmlList:XMLList = xml.image;
-
-
for (var i:int = 0; i <xmlList.length(); i++)
-
{
-
var imagePath:String = String(xmlList[i])
-
bulkInstance.add(imagePath);
-
-
//Add path to array for later access
-
images.push(imagePath);
-
}
-
-
//Set our number of items based on how many images we load
-
numItems = images.length;
-
}
When our images are ready we can continue the process of setting up our coverflow. But now using the images we just loaded for our materials.
-
var mat:BitmapMaterial = new BitmapMaterial(bulkInstance.getBitmapData(images[i]));
It's that simple. Be sure to let us know if you find this useful and are able to use it in a project.
Here is the full code:
-
package
-
{
-
import br.com.stimuli.loading.BulkLoader;
-
import br.com.stimuli.loading.BulkProgressEvent;
-
import flash.display.Sprite;
-
import flash.events.MouseEvent;
-
import flash.filters.GlowFilter;
-
import gs.easing.Quint;
-
import gs.TweenLite;
-
import org.papervision3d.events.InteractiveScene3DEvent;
-
import org.papervision3d.materials.BitmapMaterial;
-
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 images:Array = [];
-
protected var numItems:Number;
-
protected var currentItem:Number = 3;
-
protected var angle:Number = 25;
-
protected var rightBtn:Sprite;
-
protected var leftBtn:Sprite;
-
protected var xmlPath:String = "xml/imageXML.xml";
-
protected var bulkInstance:BulkLoader;
-
-
public function Main():void
-
{
-
//Make sure that your scene is set to interactive
-
super(640, 480, true, true);
-
loadXML();
-
}
-
-
//First load our XML
-
protected function loadXML():void
-
{
-
bulkInstance = new BulkLoader("bulkInstance");
-
bulkInstance.add(xmlPath);
-
bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
-
bulkInstance.start();
-
}
-
-
//When our xml is ready parse and load our images
-
protected function onXMLReady(evt:BulkProgressEvent):void
-
{
-
bulkInstance.removeEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
-
bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onImagesReady);
-
-
var xml:XML = bulkInstance.getXML(xmlPath);
-
var xmlList:XMLList = xml.image;
-
-
for (var i:int = 0; i <xmlList.length(); i++)
-
{
-
var imagePath:String = String(xmlList[i])
-
bulkInstance.add(imagePath);
-
-
//Add path to array for later access
-
images.push(imagePath);
-
}
-
-
//Set our number of items based on how many images we load
-
numItems = images.length;
-
}
-
-
//Images are finished loading we can now create our papervision coverflow
-
protected function onImagesReady(evt:BulkProgressEvent):void
-
{
-
init();
-
}
-
-
protected function init():void
-
{
-
createChildren();
-
createNavigation();
-
animate();
-
startRendering();
-
}
-
protected function createChildren():void
-
{
-
for (var i:int = 0; i <numItems; i++)
-
{
-
//Grab our bitmapData from the bulkLoader using our array of image paths as our key
-
var mat:BitmapMaterial = new BitmapMaterial(bulkInstance.getBitmapData(images[i]));
-
mat.interactive = true;
-
mat.smooth = true;
-
var plane:Plane = new Plane(mat, 280, 351, 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 = 50;
-
}
-
-
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;
-
}
-
}
-
}



Why do you use “InteractiveScene3DEvent” for a plane instead of a MouseEvent?
Nate
When you’re applying these types of events to a Plane object you need to use InteractiveScene3DEvent. You can apply MouseEvents to MovieClips and Sprites which are sometimes used with materials of Planes.
Cool Component! Thanks. I tried to add it into a Flex project and it almost worked. It hung up sometime after loading the iphone picture. Thanks for any tips!
<![CDATA[
import mx.core.UIComponent;
import flash.display.Sprite;
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;
import org.papervision3d.cameras.CameraType;
import org.papervision3d.render.BasicRenderEngine;
/**
* ...
* @author Charlie Schulze, charlie[at]woveninteractive[dot]com
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*/
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 view:BasicView;
public function init():void
{
//Make sure that your scene is set to interactive
view = new BasicView(640, 480, true, true, CameraType.TARGET);
view.renderer = new BasicRenderEngine();
// these 3 lines are key to putting Papervision in Flex
var uicomp:UIComponent = new UIComponent();
GallerycanvasPv3D.addChild( uicomp );
uicomp.addChild( view );
Main();
}
protected function Main():void
{
makeChildren();
//createNavigation();
animate();
view.singleRender();
}
protected function makeChildren():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
view.scene.addChild(plane);
}
//cam.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 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.
*/
//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 (planes.length – 1))
{
currentItem = planes.length – 1;
}
//Call animation
animate();
}
]]>
Hey Chuck,
Sorry for the late reply. I am not sure if you got this coverflow fully working in Flex yet. Here is an example of this class working with Flex.
http://pastebin.com/f6566f277
Charlie
I’m pretty new to this, so I was wondering if its possible to add a link from each photo inside of the XML?