Add

PageFlip + Tweener AS3 Part 1


Update: I had a bit of an oversight in the code. This should be using the setChildIndex method instead of swap depths. I've added more pages, updated the code, and thanks to Harry Burt for catching that. Also thanks to him for the addition of the page turning back code. There still is an issue with depth levels if the user clicks on the pages too fast. Still haven't had time to address that, but I think by adding a dispatcher at the midway point, the depth can be set then.

I'm sure most people have had the urge/need to do some sort of interface using that slick page flipping code that was floating around in the AS1 and AS2 heyday. They might be slightly dated, but I still like them in the right context. Obviously you can find the AS2 version out there. As for AS3, if you're lazy efficient like me, you did a search to see what was out there. First I came across Didier Brun's class PageFlip which is located Here. He gives a great example but you are only left with the usage code of this:

var render:Shape=new Shape();
var page0:BitmapData=new page0().bitmapData;
var page1:BitmapData=new page1().bitmapData;
 
render.x=50;
render.y=50;
addChild(render);
 
 
var o:Object=PageFlip.computeFlip(	new Point(60,190),	// flipped point
						new Point(1,1),		// of bottom-right corner
						page0.width,		// size of the sheet
						page1.height,
						true,				// in horizontal mode
						1);					// sensibility to one 
 
 
PageFlip.drawBitmapSheet(o,					// computeflip returned object
						render,					// target
						page0,		// bitmap page 0
						page1);		// bitmap page 1

That's great, but more then likely it left you wondering what came next. Didier's excellent class is the foundation for all that is page flipping in AS3 (unless of course you want to reinvent the wheel). That being said, the next step was seeing hoe to put the core code into action. My next search took me to Ruben Swieringa's site. He has an amazing and fully functioning flex application using Didier's PageFlip class. Check it out Here. Pretty solid and feature rich, and it's available for use. Kudos to him. However, if you are like me and you don't work with flex, Ruben's fine work simply serves as an example of the complexity of making the book fully interactive.

So I decided to embark on my own simpler, AS3 only version. I doubt it will be nearly as feature rich as Ruben's flex version, but at the very least I can post a moving foundation for people to see and build upon.

I think the most exciting thing for me was how easy it was to use Tweener to flip a page using its bezier property along with it's onUpdate callback.

This movie requires Flash Player 9

This is great for a flipPage() method, but obviously we'll want to turn the page with mouse interaction as well. More of that to come later. But for the time being here's the Page class with a simple turning animation and some events:

package com.hydrotik.book{
	import flash.display.Sprite;
	import flash.display.Shape;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.MouseEvent;
	import flash.events.EventDispatcher;
	import flash.geom.Point;
 
	import com.foxaweb.pageflip.PageFlip;
 
	import caurina.transitions.Tweener;
 
	public class Page extends EventDispatcher {
 
		private var _scope:*;
 
		private var flip:Point;
 
		private var front:BitmapData;
 
		private var back:BitmapData;
 
		private var render:Shape;
 
		private var _width:Number;
 
		private var _height:Number;
 
		private var _page:Sprite;
 
		private var _oPage:Page;
 
		private var _name:String;
 
 
		public function getName():String {
			return _name;
		}
 
 
		public function Page(scope:*, w:Number, h:Number, x:Number, y:Number, m1:*, m2:*, name:String) {
			_scope = scope;
			_width = w;
			_height = h;
			_oPage = this;
 
			trace(_oPage);
			_name = name;
			_page = new Sprite()
			_page.x = x;
			_page.y = y;
			_scope.addChild(_page);
 
			render = new Shape();
			_page.addChild(render);
 
			front = new BitmapData(_width, _height, true, 0);
			front.draw(m1);
			back = new BitmapData(_width, _height, true, 0);
			back.draw(m2);
 
			flip = new Point(_width, _height);
			drawPage();
			_page.addEventListener(MouseEvent.CLICK, turnPageForward);
		}
 
		private function turnPageForward(event:MouseEvent = null):void{
			dispatchEvent(new PageEvent(PageEvent.FLIP_START, _page, _oPage, true));
			_page.removeEventListener(MouseEvent.CLICK, turnPageForward);
			_page.addEventListener(MouseEvent.CLICK, turnPageBack);
 
 
			Tweener.addTween(flip, {
				x:-_width,
				y:_height,
				_bezier:{x:0, y:0},
				time:1.5,
				transition:"easeinoutexpo",
				onUpdate:drawPage,
				onComplete:onPageDone
			});
		}
 
		private function turnPageBack(event:MouseEvent = null):void{
			dispatchEvent(new PageEvent(PageEvent.FLIP_START, _page, _oPage, true)); 
            _page.addEventListener(MouseEvent.CLICK, turnPageForward);
            _page.removeEventListener(MouseEvent.CLICK, turnPageBack);
 
 
            Tweener.addTween(flip, {
                x:_width,
                y:_height,
                _bezier:{x:0, y:0},
                time:1.5,
                transition:"easeinoutexpo", 
                onUpdate:drawPage,
                onComplete:onPageDone
            });
        }
 
		private function drawPage():void{
			render.graphics.clear()
			var o:Object = PageFlip.computeFlip(flip,// flipped point
					new Point(1,1),// of bottom-right corner
					front.width,// size of the sheet
					back.height,
					true,// in horizontal mode
					1);// sensibility to one                            // sensibility to one 
			PageFlip.drawBitmapSheet(o,// computeflip returned object
					render,// target
					front,// bitmap page 0
					back);// bitmap page 1
		}
 
 
 
		private function onPageDone():void{
			dispatchEvent(new PageEvent(PageEvent.FLIP_COMPLETE, _page, _oPage, true));
		}
 
	}
 
}

Here's the custom PageEvent class:

package com.hydrotik.book {
 
	import flash.events.Event;
 
 
    public class PageEvent extends Event {
 
		public static const FLIP_START:String = "flipStart";
 
		public static const FLIP_COMPLETE:String = "flipComplete";
 
		public var targ:*;
 
		public var page:Page;
 
		public function PageEvent(type:String, t:*, p:Page, bubbles:Boolean = false, cancelable:Boolean = false){
			super(type, bubbles, cancelable);
			targ = t;
			page = p;
		}
	}
}

And here is the usage:

import com.hydrotik.book.Page;
import com.hydrotik.book.PageEvent;
 
 
var page5:Page = new Page(this, 200, 200, 250, 50, new Page5(), new Page6(), "Pages 5 and 6");
page5.addEventListener(PageEvent.FLIP_START, onFlipStartHandler);
page5.addEventListener(PageEvent.FLIP_COMPLETE, onFlipCompleteHandler);
 
var page3:Page = new Page(this, 200, 200, 250, 50, new Page3(), new Page4(), "Pages 3 and 4");
page3.addEventListener(PageEvent.FLIP_START, onFlipStartHandler);
page3.addEventListener(PageEvent.FLIP_COMPLETE, onFlipCompleteHandler);
 
var page1:Page = new Page(this, 200, 200, 250, 50, new Page1(), new Page2(), "Pages 1 and 2");
page1.addEventListener(PageEvent.FLIP_START, onFlipStartHandler);
page1.addEventListener(PageEvent.FLIP_COMPLETE, onFlipCompleteHandler);
 
 
var prevPage:DisplayObject;
 
function onFlipStartHandler(event:PageEvent):void{
	trace("Flip Started! " + event.page.getName() + " - " + event.targ);
	setChildIndex(event.targ,  this.numChildren - 1)
}
 
function onFlipCompleteHandler(event:PageEvent):void{
	trace("Flip Completed! " + event.page.getName() + " - " + event.targ);
	prevPage = event.targ;
}
 
stop();

Simple, and not much going on here, but it's easy to get a nice transition and we can see something happening! Next is calculating the mouse over the corner, getting a little rollover effect before turning the page, and being able to manually turn the page.

If anyone builds on this example or has one of their own, definitely let me know:)


Here's the code:

PageFlip AS3 Source Part 1

The Discussion

see what everyone is saying

  • don October 25th, 2007 at 5:26 pm #1

    Donovan, I like your approach to this by using caurinas transition package. I'm extending your work to hopefully catch up to Rubens flex package.

  • gordee August 28th, 2008 at 2:56 pm #2

    Hi there, great work. I was wondering if you had done any more to this regarding mouse Events? I'm new to AS3 and I'm curious to see how its done. Keep up the good work :)

  • djdonovan August 28th, 2008 at 3:14 pm #3

    I actually have a little bit, but not so much with interaction yet. I had fixed the depth issue, but can't seem to find the files and not sure why I didn't post it. Must have fallin through the cracks. I've removed Tweener as I've replaced it with HydroTween in all my work, although I'm using a self contained bezier function with this thing now.

    I do plan on posting an update to this once it's worthy of doing so.

    With the unit as it is now.. it's simply using a CLICK event to trigger a bezier curve to animate the position of the fold.

  • Andy September 27th, 2008 at 7:31 am #4

    Hi, good article, nice1. Interested in seeing any updates? I really do like the page flip effect, but theres very little out there for AS3 Flash CS3. Would love to see your updated version!

    cheers,
    Andy

  • Ryan October 2nd, 2008 at 7:59 am #5

    Hello, so I have everything all set in place but when its published, I am getting errors in the output window of

    ReferenceError: Error #1069: Property _bezier not found on flash.geom.Point and there is no default value.
    at caurina.transitions::Tweener$/::getPropertyValue()
    at caurina.transitions::Tweener$/::updateTweenByIndex()
    at caurina.transitions::Tweener$/::updateTweens()
    at caurina.transitions::Tweener$/onEnterFrame()

  • djdonovan October 2nd, 2008 at 8:29 am #6

    Not seeing this error on my end with the original source. maybe update the tweener package? I don't use this engine anymore, but it sounds like it just need to be updated.

  • John laPlante December 15th, 2008 at 3:50 pm #7

    I'm trying to use this for a prototype of a app that simulates folding a piece of paper.

    I did a few things to enhance your app. I added a method named 'turnPageBackward.' I hadn't used the tweener class and it took me a bit to figure out what dictates the direction of page turning. I found that by changing the tweener call form x:-_width to x:_width, I could change the direction.

    I added a new event listener to the turnPageForward method to reverse the direction the page flips.
    _page.removeEventListener(MouseEvent.CLICK,turnPageBackward); _page.addEventListener(MouseEvent.CLICK, turnPageForward);

    I'm now working on: Flipping vertically with partial success. The PageFlip.computeFlip static method has a boolean that is supposed to dictate the direction. But, so far, I've had partial results. The page begins to flip down but stops halfway and hangs from a corner. It's funny how the tween makes is look real and I want to reach out and pull it down the rest of the way :) .

  • Kapri design December 19th, 2008 at 2:51 pm #8

    Thanks man, this code really helped me out. All I kept finding were AS 2.0 classes and I was starting to worry about might having to write my own AS 3.0 page flip.

    Thanks and greetings from Amsterdam

  • djdonovan December 19th, 2008 at 2:59 pm #9

    Hey John. Yeah I came back to this for another project and it got scrapped, so I haven't had a chance to clean it up and post it. Nothing to get excited about though lol

    let me know how you make out with it. If you want I can send you what I got, or anyone else for that matter.

    Cheers

  • djdonovan December 19th, 2008 at 3:00 pm #10

    Thanks Kapri! Glad it helped… it's not much, but hopefully a start.

    Cheers!

  • ranjan January 12th, 2009 at 2:35 am #11

    Is there any AS2 version of the class?

  • djdonovan January 12th, 2009 at 4:03 pm #12

    I'm, pretty sure there are, but I don't know of any off the top of my head. maybe shoot Kapri a note?

  • nortagem January 15th, 2009 at 1:14 pm #13

    I absolutely love this code.
    HOWEVER – and pardon this noob question – how can I add event listeners to objects on the pages themselves?? Like a button located on the Page1 MC? It won't accept any btn inside the page MC itself.

    Would appreciate any help greatly…

  • Boaz February 6th, 2009 at 10:17 am #14

    Hi,
    thanks, this is great help.
    how would i make the book turn the pages automatically ?
    i want to animate a book turning pages in intervals of 3 seconds.
    thanks

  • djdonovan February 6th, 2009 at 11:26 am #15

    Folks, this code is a bit dated (2007) and is simply a jumping off point for your own development. For example I'm not even using Tweener anymore. Since this was done, I'm sure there are more further refined and posted examples.

    If you come across anything, send me a comment and I can add it to the post.

  • Flash & Flex Intermingling – Hail Mothra February 13th, 2009 at 9:19 pm #16

    [...] You said you’ll be extending Donovan’s PageFlip class http://blog.hydrotik.com/2007/08/15/pageflip-tweener-as3-part-1/#comment-478 [...]

  • kristay February 23rd, 2009 at 7:18 pm #17

    This may be a stupid question but, on exporting the swf I get
    package com.hydrotik.book{ does no reflect the location of the file please rename.

    Does this mean it's importing the package form the site and will not work unless uploaded or am I just not seeing the hydrotik package in the file?

  • djdonovan February 27th, 2009 at 11:20 am #18

    I would try downloading the source again. The classes are in the correct place and if I'm understanding you correctly it seems like you have a path issue to the classes.

  • o-g-sus November 25th, 2009 at 8:16 am #19

    hey yo,
    has anybody made some progress with manually flipping the sides?
    I am curious, and it would be a great help for me.

    cheers,

    Oliver

Respond

get in on the action.

* Required

  • Viagra ordre
  • Cialis en ligne
  • Levitra en ligne
  • Propecia acheter
  • Viagra acheter
  • Acheter cialis
  • Ordre levitra
  • Ordre propecia
  • En ligne viagra
  • Vente cialis
  • Levitra bon marche
  • Propecia en ligne
  • Viagra online
  • Buy cialis
  • Order Levitra
  • Buy propecia
  • Buy viagra
  • Cheap cialis
  • Cheap Levitra
  • propecia online
  • Viagra prescription
  • Cialis online
  • Buy Levitra
  • Order propecia