The Project
A few weeks ago, John and I over here at Producto Studios were asked to create an interactive, single-page, Power-Point style application for a small company (in Flash). The app was to contain multiple drop-down box syle animations that revealed bullet points and a screen filled with “touch” style buttons that played animations. Some animations triggered more animations, some played continuously, and some turned off all other animations once touched and played.
We always start with Flash
There is no better tool tan Flash for rapid prototyping an app like this. Plus, we never thought we would have to get this working on the iPad. Even if we did though, Flash provides the right tools on the design and export side to get this accomplished pretty quickly.
After designing the initial Flash version for a larger screen (1920 x 1080), so it could scale an look nice on a larger projector, we were then told that the client wanted to use his iPad to show the presentation. I am pretty familiar with the HTML5 Canvas (having just recently co-authored a book on the subject), so John and I decided to export the Flash assets and re-assemble them in Javascript to target the Safari browser.
Exporting From Flash to Use on the Canvas
John was able to use the Flash —>Export Movie –> PNG Sequence to create sets of individual PNG key frames right inside the Flash CS5 IDE. Once I had those, I jumped over into Javascript and created a simple HTML5 pages with the 1920 x 1080 Canvas element on it.
Pre-loading all of Those Exported Images into Javascript
The actual loading of image sets into Javascript was pretty easy using the the “tempImage.onload = loadedImage;” context. I simply had each image load (there were roughly 270 individual key image frames to load) call the same function and kept a count of how many where loaded before moving on with the application.
Showing a Flash-Like Pre-loader
To make the pre-load a little more Flash-like, I added a Canvas text string that simply said “Loading…” while these load operations were occurring.
Mimicking Flash-Like Interactive Objects
Once the images were loaded, I created a set of generic objects to hold the properties of each type of interactive object and arrays to store them in. For example, all animation that can be clicked were placed in one array (along with x,y, width, and height) attributes. Other types of elements such as static images were placed in a separate array because they would not need to click interactions.
Detecting User Interaction On The Canvas
Detecting clicks on individual elements drawn on the Canvas is not as easy as adding an event listener (as in Flash) , so I created a function to loop through all of the interactive elements when every the Canvas was clicked and then use the x,y,width and height properties previous stored for each to check to see which was clicked.
Dirty Rect Re-Draws
I wanted to make sure that the entire canvas was not re-drawn on each animation frame, so I used that same x,y,width, and height attributes to do a “dirty-rect” back-ground replace (like a Flash screen invalidation) and re-draw. This seemed to improve the frame rate slightly and was more fun to code then simply re-drawing the entire Canvas on each update. Since some of the elements’ bounding boxes “bled” into one-another, I did need to keep a list for each element of other “dirty rects” that needed to be updated.
How long it took
The entire translation from Flash interactive demo to image export to HTML5 working demo took about 4 hours of time. There were a bunch of elements to move around and the x-y coordinates from the Flash Info Panel didn’t seem to line up directly with the Canvas pixel locations, so clean-up, bug fixing, and adding in the bulk of the specialized user functionality too up roughly another 4 hours.
Speed of Application Execution
The Interaction speed difference between Flash and the new HTML5 Canvas version was completely unnoticeable. They were virtually identical.
Going Mobile
Then I posted it out our test site and tried it out on the iPad. While it did load pretty fast, the frame rate was about 1/2 that of the Safari Mac version. I upped the frame rate from 10 to 20 and this did seem to help a lot (luckily I had that option because we started in Flash at such a slow Frame Rate).
The biggest problem was the size. The 1920 width would not auto-scale to the iPad (landscape) screen so we were forced to scroll left and right to get the entire app in view and usable. I did some Safari Mobile searches and found some Meta Tags that seemed to help and some that did absolutely nothing to help at all.
The one that seemed to help the best was setting the initial scale to 50% (the iPad width is 960).
<meta name=”viewport” content=”width=device-width, initial-scale=0.5″/>
While this worked great size-wise, it slowed down the iteration even more. Luckuly I was still only at 20 FPS, so I upped my animation frame interval to 30 FPS and everything seemed to work ok.
The client was happy, but I was a little disappointed in how technically challenging it was to get the Safari Mobile browser to perform and scale to my liking.
What I will try for the next, similar app:
1. Design from 960 width from the beginning
2. Attempt to use CSS3 and either transforms or multiple Canvas elements to see if the speed is any better.
If you have any other ideas that might help out on a project like this in the future, please let me know. I am very interested in trying CSS3 an d multiple Canvas elements.