I’ve made some much needed performance improvements to the Flex CoverFlow component I released a few days ago. I’ve also taken the concept of 3D Flex containers a little further and added a 3D Carousel container and a vertical version of CoverFlow. Source code here.
Check out the performance now and stop whining (oh, and notice that this blog post has 3 of these embedded 3D components):
When I first released the component I took the shotgun approach to rendering, which meant I rendered the entire scene every frame and all the materials were animated. This is the lazy approach that ensures that the 3D scene always looks right, but it also kills performance. So you poor people out there with computers from the 1980s complained that the component made your browser shoot up to 110% cpu and all that. Instead of telling you to get faster computers I decided to make a few small modifications to speed things up.
First, instead of rendering every frame we’re now rendering only while the animation is happening. This is a sweet improvement that Brock Brinkerhoff suggested in an email he sent me (thanks Brock!). Basically in our enter frame handler we check if Tweener is currently tweening the selected child. If so, we make PaperVision 3D render the scene. If not we just ignore and don’t waste CPU power. This means that once the movement has stopped (ie the selected child comes to rest in the center), the component no longer uses much CPU at all.
The second improvement was to not use animated materials. I added a new material that I called
FlexMaterial (and the associated reflected version,
ReflectionFlexMaterial). This material is non animated, but listens for
FlexEvent.UPDATE_COMPLETE events fired from the child (and all of the child’s children if it has any). Whenever an
updateComplete event fires the material re-renders. This ensures that our material is always up-to-date. One note about this: if you have animations in your child components that do not dispatch
updateComplete events you’ll have to manually dispatch
updateComplete over and over. This is pretty easy, basically what I did for a child that I wanted animated was add the following code in MXML:
and that ensures that the child will always be updated.
Oh, and while I was at it I made a modification to get around the z-ordering issue. This was a problem when you selected one of the planes that was not directly next to the selected one. When the selected plane moved back into place it would move through the other planes on its way. Now we push the selected plane straight back at a faster rate than it moves sideways, seems to have pretty much fixed the issue (at least good enough for my eyes).
I refactored the code a little bit to allow me to easily change the 3D layout. This let me crank out a vertical version of the CoverFlow component in no time, shown here on the right. This is almost all the same code, just tweaked to lay things out vertically instead of horizontally. I figure this can be used for a sidebar widget. I had to remove the sweet web 2.0 reflections cause I didn’t know where they would go. The cool part about the refactored code is that the base component handles all the core stuff (like creating the 3d scene and planes, etc) and then each extension can simply modify the layout method. Sweet.
Carousel Flex Component
And while I was playing I couldn’t help taking some of Lee Brimelow’s code and making a 3D carousel Flex component. Thanks to Lee for doing the math for me. So here’s a Flex container to do that 3D carousel thingy. One sweet thing is that I took the same approach to preserve full interactivity of the child components. When the selected child is rotated to completely face the user the real child is swapped with the 3D plane and you can fully interact with it just like in a normal Flex app.
Take it further
So if you take a look at the source code you’ll see that I’ve created a
BasePV3DContainer, which extends ViewStack and creates 3D planes for each child in the container. The idea here is that you can create an extension of this class and implement the
layoutChildren() method and make up your own 3D container component. I wouldn’t say the base class I’ve provided is perfect, there’s certainly some code that should get moved around or done differently, but you can figure it out (hell, it’s only 300 some lines of code with comments). If you make any other 3D container Flex components then either post a comment here or drop me an email: doug.
Get the source
(Note that this source package include the CoverFlow, Vertical CoverFlow, and Carousel components, as well as an example showing using the CoverFlow component with Flex controls. This does not include the iTunes examples in this post. I’m too lazy to clean that code up well enough to give out.)