15

Papervision + Tweener + AS3 – Flipping Banner


UPDATE: Since I'm having problems with the SWF embedding, download the files to preview. Also be sure to check out the newer version with PV3D 2.0

Here's a little simple and practical application I had to put together for work using papervision. Nothing to write home about. Just a real world example that proves how easy it is to add papervision to your daily workflow. All this does is load a set of images from an XML file and papervision transitions from one to the other by flipping the plane using Tweener.

Core class:

package com.hydrotik.pageflip{
 
	/**
	 * @author Donovan Adams
	 * @version Sept 16, 2007
	 * @description Papervision Page flip example
	 * 
	 */
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.text.StyleSheet;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFieldAutoSize;
	import flash.filters.BlurFilter;
 
	import caurina.transitions.Tweener;
 
	import com.hydrotik.utils.XMLManager;
	import com.hydrotik.pageflip.Flip;
	import com.hydrotik.pageflip.FlipEvent;
 
	public class Core extends Sprite {
 
		private var _scope:MovieClip;
 
		private var _stage:Stage;
 
		private var _url:String;
 
		private var _xml:XML;
 
		private var url:String;
 
		private var _hit:Sprite;
 
		public function Core(scope:MovieClip, stage:Stage):void {
			_scope = scope;
			_stage = stage;
			_url = _scope.loaderInfo.url;
			var xml:XMLManager = new XMLManager("../includes/admin/flippingbanner.xml");
			xml.addEventListener("evtXMLLoaded", onXMLComplete);
		}
 
 
		// --== Private Methods ==--
		private function onXMLComplete(event:Event):void {
			trace(":: onXMLComplete:");
			_xml = event.target.xml;
 
			var _oFlip:Flip = new Flip(_scope, _stage, this, _xml.banner.children(), _xml.attribute("seconds"));
			_oFlip.addEventListener(FlipEvent.COMPLETE, onCompleteHandler);
			_oFlip.addEventListener(FlipEvent.ON_FLIP, onFlipHandler);
 
			_hit = new Sprite();
			_hit.graphics.beginFill(0x660000, 0);
			_hit.graphics.drawRect(0, 0, 300, 156);
			_scope.addChild(_hit);
			_hit.addEventListener(MouseEvent.CLICK, onClickHandler);
 
			_hit.buttonMode = true;
			_hit.useHandCursor = true;
			_hit.mouseEnabled = true;
		}
 
		private function onClickHandler(event:MouseEvent):void {
			trace("url: " + url);
			var request:URLRequest = new URLRequest(url);
			try {
				navigateToURL(request, "_self");
			} catch (e:Error) {
				// handle error here
			}
		}
 
		private function onCompleteHandler(event:FlipEvent):void {
			trace(event);
			url = event.url;
		}
 
		private function onFlipHandler(event:FlipEvent):void {
			trace(event);
			url = event.url;
		}
 
	}
}

Flipping code:

package com.hydrotik.pageflip{
 
	/**
	 * @author Donovan Adams
	 * @version July 10, 2007
	 * @usage Example:<code></code>
	 * @description
	 * @history
	 * @sends
	 * @todo
	 * 
	 */
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.filters.BitmapFilter;
	import flash.filters.BitmapFilterQuality;
	import flash.filters.BlurFilter;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.display.*;
	import org.papervision3d.cameras.FreeCamera3D;
	import org.papervision3d.core.*;
	import org.papervision3d.core.geom.Vertex3D;
	import org.papervision3d.materials.InteractiveMovieAssetMaterial;
	import org.papervision3d.materials.BitmapFileMaterial;
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.objects.Plane;
	import org.papervision3d.scenes.InteractiveScene3D;
	import org.papervision3d.events.InteractiveScene3DEvent;
	import org.papervision3d.events.FileLoadEvent;
	import org.papervision3d.utils.*;
 
	import caurina.transitions.Tweener;
 
	import com.hydrotik.pageflip.FlipEvent;
 
	public class Flip extends EventDispatcher {
 
		private var _scope:Sprite;
 
		private var _stage:Stage;
 
		private var _oCore:*;
 
		private var _assetPath:String;
 
		private var container:Sprite;
 
		private var scene:InteractiveScene3D;
 
		private var camera:FreeCamera3D;
 
		private var _materialArray:Array;
 
		private var _planeArray:Array;
 
		private var _array:XMLList;
 
		private var _count:int = 0;
 
		private var _next:Plane;
 
		private var _prev:Plane;
 
		private var _shadowPlane:Plane;
 
		private var _loader:Sprite;
 
		private var url:String;
 
		private var _id:int;
 
		private var _seconds:int;
 
		public function Flip(scope:Sprite, stage:Stage, core:*, a:XMLList, assetPath:String = "../flashassets/", s:int = 10):void {
			_scope = scope;
			_stage = stage;
			_oCore = core;
			_array = a;
			_assetPath = assetPath;
			_seconds = s;
			_materialArray = [];
			_planeArray = [];
 
			// Add Container
			container = new Sprite();
			container.x = stage.stageWidth/2;
			container.y = stage.stageHeight/2;
			_scope.addChild( container );
 
			scene = new InteractiveScene3D( container );
 
			camera = new FreeCamera3D();
			camera.z = -500;
 
			_loader = new Sprite();
			_loader.graphics.beginFill(0x000000);
			_loader.graphics.drawRect(0, 0, 1, 4);
			_scope.addChild(_loader);
			_loader.x = (stage.stageWidth/2) - 50;
			_loader.y = (stage.stageHeight/2) - 2;
 
			var colorMaterial:ColorMaterial = new ColorMaterial(0x000000, .2);
			_shadowPlane = new Plane( colorMaterial, stage.stageWidth, 50, 6, 6);
			_shadowPlane.y = -150;
			_shadowPlane.z = 50;
			_shadowPlane.rotationX = -90;
			_shadowPlane.rotationY = -180;
			scene.addChild(_shadowPlane);
 
			var filter:BitmapFilter = getBitmapFilter();
			var myFilters:Array = new Array();
			myFilters.push(filter);
			_shadowPlane.container.filters = myFilters;
			_shadowPlane.container.alpha = 0;
 
			for (var i:int = 0; i < _array.length(); i++) {
				_materialArray[i] = new BitmapFileMaterial(_array[i].attribute('src'));
				_materialArray[i].doubleSided = false;
				_materialArray[i].smooth = true;
				_materialArray[i].addEventListener(FileLoadEvent.LOAD_PROGRESS, onFileProgress);
				_materialArray[i].addEventListener(FileLoadEvent.LOAD_COMPLETE, onFileComplete);
				_planeArray[i] = new Plane( _materialArray[i], stage.stageWidth, stage.stageHeight, 6, 6);
				scene.addChild( _planeArray[i] );
				_planeArray[i].name = i.toString();
				_planeArray[i].rotationY = -180;
				_planeArray[i].container.alpha = 0;
			}
 
 
			// render the scene once
			scene.renderCamera( camera );
		}
 
 
 
		private function flip(id:int):void {
			Tweener.addTween(_next.container, {
				alpha:0,
				time:1,
				transition:"easeoutquint"
			});
			Tweener.addTween([_next, _shadowPlane], {
				rotationY:180,
				time:1,
				transition:"easeoutquint",
				onComplete:onOldFlipDone
			});
 
			// Update Data
			_prev = _next;
			_id = (id == _array.length() - 1) ? 0 : id + 1;
			_next = _planeArray[_id];
			url = _array[_id].attribute('link');
 
			dispatchEvent(new FlipEvent(FlipEvent.ON_FLIP, _id, _next.container, url));
 
			Tweener.addTween(_next.container, {
				alpha:1,
				time:1,
				transition:"easeoutquint"
			});
			Tweener.addTween([_next], {
				rotationY:0,
				time:1,
				transition:"easeoutquint",
				onUpdate:draw,
				onComplete:onFlipDone
			});
			Tweener.addTween(camera, {
				z:-100,
				_bezier:[{z:-350}, {z:-100}],
				time:2,
				transition:"easeoutquint"
			});
		}
 
 
		private function onFileProgress(event:FileLoadEvent):void {
			trace("\t percentage: "+Math.round((event.bytesLoaded/event.bytesTotal)*100) + "%");
			var sec:Number = 100/_array.length();
			_loader.width = ((_count * sec) + ((event.bytesLoaded/event.bytesTotal) * sec));
		}
 
		private function onFileComplete(event:FileLoadEvent):void {
			trace("complete!");
			scene.renderCamera( camera );
			_count++;
			if (_count == _array.length()) {
				onImageQueueCompleteHandler();
			}
		}
 
		private function onImageQueueCompleteHandler():void {
			dispatchEvent(new FlipEvent(FlipEvent.COMPLETE, 0, _planeArray[0].container, _array[0].attribute('link')));
			Tweener.addTween(_loader, {
				alpha:0,
				time:.2,
				transition:"easeoutquint",
				onComplete:loaderFade
			});
 
 
			trace("** papervision queue complete!!");
			Tweener.addTween([_planeArray[0].container, _shadowPlane.container], {
				alpha:1,
				time:1,
				transition:"easeoutquint"
			});
			Tweener.addTween([_planeArray[0], _shadowPlane], {
				rotationY:0,
				time:1,
				transition:"easeoutquint",
				onUpdate:draw,
				onComplete:onFlipDone
			});
			Tweener.addTween(camera, {
				z:-100,
				time:1,
				transition:"easeoutquint"
			});
			_next = _planeArray[0];
 
			_count = -1;
 
			var myTimer:Timer = new Timer(_seconds * 1000);
			myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
			myTimer.start();
		}
 
		public function timerHandler(event:TimerEvent):void {
			trace("timerHandler: " + event);
			_count = (_count == _array.length() - 1) ? 0 : _count + 1;
			flip(new Number(_count));
		}
 
		private function draw():void {
			scene.renderCamera( camera );
		}
 
		private function onFlipDone():void {
			trace("flip done!");
 
		}
 
		private function loaderFade():void {
			_scope.removeChild(_loader);
		}
 
		private function onOldFlipDone():void {
			trace("old flip done!");
			_prev.rotationY = -180;
			_shadowPlane.rotationY = 0;
		}
 
		private function getBitmapFilter():BitmapFilter {
			var blurX:Number = 5;
			var blurY:Number = 5;
			return new BlurFilter(blurX,blurY,BitmapFilterQuality.HIGH);
		}
	}
}

Papervision is constantly going through new revs so keep in mind this is not the most recent. You'll see the Flip custom event, and a little XML loading utility in the source. Note that the Core file is just the main class. It could be your main timeline for all intents and purposes. Also the loader calculates the total images. I added a shadow plane just for a slight touch but that would lend itself to a white background and fixed banner sizes. A little breathing room for the shadow would be good if you wanted to enhance the effect. It's just a jumping off point for more, so have fun! :)

Like I said, nothing too fancy. Enjoy!


Papervision Flipping Banner Source

bottega veneta deep coffee pocket bag deep weight loss pills bingo and game casino gambling online virtual how to win at slots versace deep coffee venus bag women does viagra work online bingo uk discount drugstore where to get viagra or cialis diazepam cheap without rx bingo and slots does cialis really work bingo gaming chanel yellow shoulder bag bingo for cash slot machine buy meds online without presciption lancel pearl premier flirt prada white shoulder bag prescriptions pain killers without a prescription viagra product information cialis generic levitra viagra cialis male enhancement online gambling offers manolo blahnik beige hangisi valium indications anya hindmarch beige hobo how does diazepam work who has the cheapest cialis price for tramadol levitra website price for generic viagra top anti depressants pharmacy zolpidem marc jacobs antique gold keylock messenger bag pill for acne casino gambling buy carisoprodol cheap create poker website zyban tablet jimmy choo purple wells shoes valtrex medication counseling for erectile dysfunction hey bingo louis vuitton patent beige sandals louis vuitton monogram idylle pink tote power bingo slot games gucci black evening bag xanax fedex oral jelly viagra new casino slots discount erectile dysfunction medication christian louboutin white ambrosina pumps poker machine games buy no phentermine prescription high stakes poker buy tory burch golden reva ballerina flats casino locations roulette casinos play online casinos bingo and slots viagra effect on women louis vuitton damier graphite keepall bandouliere marc jacobs royal blue keylock shoulder bag play roulette online casino mania online buy compazine buy gucci black trainers online casinos en internet how to win slots christian louboutin blush barcelona sandals prescription diet drugs us only mobile casino games natural clomid buy overseas viagra online casino canada online xanax fedex norvasc generic erectile dysfunction products zoloft canada uk viagra supplier casino bonus tory burch deep blue tory logo rain boots poker for money prescription drugs online adipex no prescription needed pharmacies geniune cialis no prescription ambien dosing how do muscle relaxants work valentino beige snakeskin clutch what is tadalafil ativan dosages sales viagra ysl white muse bag cialis to buy online gambling strategy cheapest phentermine pills christian dior biege medium saddle handbag alprazolam brand cheap viagra new zealand low cost adipex bally patent patent red jana tote ambien pharmacy manolo blahnik bow booties what is viagra used for dosage viagra new diet pill fda approved play slots online now cialis best price las vegas bingo cialis generic tabs versace purple venita bow satchel chloe patent purple cyndi tote fendi apricot snake peekaboo handbag discount lipitor prescription ambien ambien 10mg poker us levitra free samples do meridia phentermine work the same order celine black shoulder bag louis vuitton patent black sandals over the counter medication cheap 37 5 phentermine safe effective diet pills loewe white handbag dolce gabbana black trainers buying phentermine alprazolam generic for xanax ativan 2mg prada beige fairy l bag generic cialis canadian diet phentermine viagra online cheap europe cialis platinum play bingo levitra info prescription drugs migraines levitra alternative phentermine ingredient how does cialis work louis vuitton damier azure canvas galliera gm order amoxicillin new arthritis and psoriasis drug lipitor online pharmacy professional blackjack how does cialis ultram ingredients