MadComponents3D – part3: Page Flipping
In the previous instalment we looked at the grid scrolling components that mimic the behaviour of a Windows Metro UI for your Flash or AIR applications.
If you downloaded the open-source beta – you may want to update from the code repository – as I’ve added a few optimisation tweaks and fixes since.
I’ve moved the SVN source: It’s at http://code.google.com/p/mad-components/source/browse/trunk/MadComponents3D/
There’s also a new demo. The source code is here.
In this new instalment, we’ll be talking about the page-flipping capabilities of MC3D. This youtube video mostly shows page-flipping in action. (Although I made it during development – so the experience is slightly more polished now).
There are four page-flipping modes.
In all four cases, when you activate a flipping mode, the current page slides back so that you see it in context with other pages. Within a flipping mode, the page isn’t interactive, as any touch event will be interpreted as flip gesture. A single tap will zoom the current page back into a normal MadComponents view, so you can interact with it again.
I’ve used chart pages in the demo, because they look nice. But you can customise the layout to use any MadComponents layout, including interactive elements such as buttons, inputs, pickers, lists, etc.
Delving into the code
You’ll notice that some MC3D classes are suffixed by the letter E. There’s PageFlipping.as class, and a more recent PageFlippingE.as class. (There’s also GridScrollingE.as, etc.).
While I was developing MC3D, I would first implement the algorithm in the most straightforward way. Then later, when I experimented with optimisations and refinements – I would extend and override the original class. Hence “E”.
One of the “E”-version optimisations is to represent each page with a tiled arrangement of 128×128 texture squares. This is handled by the GridPage.as class. It has been reported that multiple small texture uploads are faster than a large texture upload. (Although Stage3D texture uploads are still pathetically slow in either case).
The other advantage with a grid arrangement of textures is that you can replace any individual square texture – without having to reload all textures. This means that if any component on a page changes – (flipping a switch, typing text into an input, changing a picker, etc.) – just refresh the relevant squares – not the entire page.
As with most of the MC3D classes, I’ve employed some clever vertex and fragment shaders. The vertex shader interpolates from page corner vertices to arrive at the vertices for each comprising grid square. There’s fragment shader that generates a reflected image, rendered as a gradient, fading to black.
Unless someone reports that the non-”E” classes perform better in some respect – it is probably best to assume that they are depreciated in favour o the “E”" classes. At some stage – we might flatten the classes to remove obsolete code.
I said “we” – as this popular open source currently has very little contribution from anyone else. It irritates me intensely that Adobe have thrown their weight behind less mature, and less capable alternatives. A direction that is obviously furthering someone’s career inside Adobe – and has absolutely nothing to do with benefiting the developer community.
So as my allegiance shifts towards certain competitors of Adobe AIR in the mobile space, my support for MC3D will diminish. But it’s a worthwhile project, and it would be great to find a champion or two to ensure it continues.
Using this effect in your own projects
public function set snapToPage(value:Boolean):void
public function get snapToPage()
Page snapping, ensures that the current page in centre on the screen.
public function containerPageTextures(container:IContainerUI, showPageIndicator:Boolean = false):void
Specify a container component such as <navigation>, <pages>, <tabPages>, etc. This method will capture the textures of all the pages.
public function pageTextures(width:Number, height:Number, pages:Vector.<Sprite>, showPageIndicator:Boolean, backgroundColour:uint = 0xFFFFFF):void
Specify page textures as a Vector of Sprites. (Use this as an alternative to containerPageTextures).
public function updatePage(pageNumber:int, component:DisplayObject = null):void
Update the textures for a particular component on a page. (The page is represented by a grid of textures, so only updates relevant squares).
public function get pageNumber():int
public function set pageNumber(value:int):void
Current page number.
public function madPages(zoomInOnClick:Boolean = false):void
Switch out of page-flipping mode and go into normal interactive MadComponents mode.
public function zoomOutToMadPages(zoomInOnClick:Boolean = false):void
An animation to switch out of page-flipping mode and go into normal interactive MadComponents mode.
public function madFlow(zoomInOnClick:Boolean = false):void
Switch to MadFlow mode.
public function zoomOutToMadFlow(zoomInOnClick:Boolean = false):void
Animate into MadFlow mode.
public function madSwap(zoomInOnClick:Boolean = false, spin:Boolean = false):void
Switch to MadSwap mode.
public function zoomOutToMadSwap(zoomInOnClick:Boolean = false, spin:Boolean = false):voidpublic function
Animate into MadSwap mode.
public function madCircular(zoomInOnClick:Boolean = false, spin:Boolean = false):void
Switch to MadCircular mode.
zoomOutToMadCircular(zoomInOnClick:Boolean = false, spin:Boolean = false):void
Animate into MadCircular mode.
public function zoomInToPage():void
Animate to interactive MadComponents mode.
public function loadPage(pageNumber:int, backgroundColour:uint = 0xFFFFFFFF):void
Replace a page with a new texture.