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(0×660000, 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:<div class="codesnip-container" ></div>
         * @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(0×000000);
                        _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(0×000000, .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

15 Responses to “Papervision + Tweener + AS3 - Flipping Banner”

  1. labs.zeh.com.br » Blog Archive » Misc Tweener links and cool examples to look at Says:

    [...] an slightly similar note, Donovan Adams has examples of a flipping banner using Papervision3D and Tweener. Sources are [...]

  2. felix Says:

    it keeps reloading the page when I click on the swf… (os x /firefox)

  3. djdonovan Says:

    The links in the XML are set to go to this page. I didn't get a change to add a target window attribute to the xml doc.

  4. Neo Says:

    It looks cool~

  5. Jon Marston Says:

    Thanks for the example, very cool. One problem:
    The zip file example has one hardcoded path. I needed to change line 49 of core.as to be "var xml:XMLManager = new XMLManager("../includes/admin/flippingbanner.xml");"

  6. djdonovan Says:

    Nothing wrong with changing the path. I never intended this to be completely plug and play, although I suppose it is for the most part. I invite everyone to modify this and expand on it.:)

  7. saravanan Says:

    Hi, is there way to return bitmap data seperately as u use in XMLManager class..

    that is we just pass the url and the BitmapManager class should return bitmapdata ..

    is it posible

    thanks in advance

  8. djdonovan Says:

    Not sure I follow you. I'm not using any bitmap object in the xml class. Are you referring to a custom event for loading Bitmaps into Papervision? This might be a question for the papervision list in using the BitmapFileMaterial class?

  9. Tercüme bürosu Says:

    it keeps reloading the page when I click on the swf..

  10. djdonovan Says:

    See above.

  11. Andrei Potorac Says:

    Congrats for this amazing file! I've been searching for this for some time. :)

  12. Andrei Potorac Says:

    I found a bug. In the flip constructor, you have a variable which is read instead of the variable from the XML for the seconds, so no matter what value you put in the XML for the seconds, it won't read it. You should remove this from the constructor:

    assetPath:String = "../flashassets/",

    :)

  13. djdonovan Says:

    In Core line 59 should read:

    var _oFlip:Flip = new Flip(_scope, _stage, this, _xml.banner.children(), "", _xml.attribute("seconds"));
  14. djdonovan Says:

    Papervision 2.0 example has been added here.

  15. Zeh Fernando » Blog Archive » Misc Tweener links and cool examples to look at Says:

    [...] an slightly similar note, Donovan Adams has examples of a flipping banner using Papervision3D and Tweener. Sources are [...]

Leave a Reply







September 2007
M T W T F S S
« Aug   Oct »
 12
3456789
10111213141516
17181920212223
24252627282930
  • Archives

  • Other

  • Syndication