Fixing IE by porting Canvas to Flash
This is a guest blog from Grant Jones.
My hat is off to Grant for the awesome work he’s done, as well as for writing this post.
Intro to Internet Explorer Canvas-Emulation
Before we go into the current state of Internet Explorer canvas-emulation, here’s a brief look back at the history – or the history as far as I could tell from blog posts:
- Manish Jethani mentions something about the canvas tag being used for a 3D game, John Dowdell from adobe responds in Nov. 2005
- Manish Jethani suggests a way to do a SWF-based Canvas on Dec 1st, 2005
- iecanvas from Emil A Eklund released December, 2005 (uses VML)
- excanvas from Google released March, 2006 (uses VML)
- AFLAX (uses ExternalInterface) adds canvas emulation in March 2006
Overall, interest in this area seems to die off after that. Only recently with things like Processing.js and ContextFree.js has there been a renewed interested in backwards compatibility for the canvas tag.
What is FlashCanvas?
Firefox, Safari and Opera 9 support the canvas tag to allow 2D command-based drawing. ExplorerCanvas brings the same functionality to Internet Explorer. To use, web developers only need to include a single script tag in their existing web pages.
How does FlashCanvas work?
FlashCanvas is modeled after ExplorerCanvas which means it is a turn-key solution for adding Canvas support to IE. You can code away, happily using open standards and then use FlashCanvas to forcefully and silently upgrade IE to also being standards compliant.
There are two main components in FlashCanvas: the base FlashCanvas.swf flash file (a mere 688 bytes), and the FlashCanvas.js wrapper. I’ve used the excellent swfobject.js to embed the Flash into the page.
Download it here: FlashCanvas 0.2.
Version 0.2 includes a batched mode. Look for the “example1_stress.htm” inside of the examples folder for a demo of it in use. It’s Released under the same Apache License as the explorer canvas project.
FlashCanvas is a one-day project, meaning that this release only implements lines and fills, which is only enought to support the first two examples from ExplorerCanvas.
Does FlashCanvas provide better performance?
The short version: not really.
FlashCanvas did not yield as much of a speed increase as I was expected. The question is, where is the slowdown occuring.
The results revealed where the problem was:
(where time is in milliseconds)
For comparison this is safari doing the same exact thing using it’s native canvas element:
(where time is in milliseconds)
The next logical step is to batching draw commands into an array to be passed only once into the flash renderer. Immediately this raises an issue about how the canvas API has been typically used: there is no explicit end of rendering or flush equivalent so the canvas-wrapper would never really know when drawing is finished. The most fine-grained control would be at the individual path level, which would result in nearly the same performance for something like the example1.htm file. Most graphics API have some sort of buffer flush either explicitly, like glFlush in opengl, or implicitly during a buffer swap.
Still, it was worth testing to see if this could solve the performance issues. A flush was added to the canvas-wrapper but batching commands into an array does not eliminate the performance problem in ExternalInterface. FlashCanvas was changed to batch commands and then send them to flash with only one call via ExternalInterface. The result is only slightly faster (800 ms instead of 1 sec and a really slow 20 secs /frame in Internet Explorer 7). Since that part of flash is all closed this was basically as far as I could go — my guess is that some sort of serialization/translation is taking all the time.
What other approaches could be taken?