IE Can what? Canvas Element for Internet Explorer
I've just finished a simple implementation of a canvas element for Microsoft Internet Explorer using VML. I needed a way to do simple line graphics for a project I'm working on, and that I want to run in both IE and Firefox. While I could have used either Java or Flash to do line graphics, now that we’re in Web 2.0 (or World 2.0, rather) and Ajax is the word, both seem a bit ... obsolete.
Here's a demo page showing what works and what doesn't. As I’ve implemented what I need and very little more, there's more of the latter than the former. Still, most of the basic stuff works:
- Outlining and filling of paths work fine. Clipping is not supported. Quadratic curves are implemented but VML does not draw them unless they are closed. There’s a lot that VML doesn’t do right.
- VML does not support gradients the way they are defined by the canvas feature. I have spent only very little time trying to simulate them, and have mostly failed. It does something, but wrong. Patterns work better, but only a little.
- Transformations work for line figures but not for patterns and images. Arcs degrade if you rotate and scale them but you may not always notice (work-around because VML is rubbish).
- Image drawing works if the source is an image. I have contemplated doing canvas sources but then didn't do them because I don't need them. That's not to say that they're difficult (*), they're just unnecessary (to me, for now).
(*) You can copy the children of the source canvas into a div and insert that into the destination canvas.
To use it, you only need to add a call to the global __initCanvas() function in the document's onload event handler, preferably before you use any of the canvas functions. It'll do no harm in Firefox, but in IE, it will replace all canvas elements in the document by div elements with the same id and size (and all other attributes). You can then request a drawing context using getContext the same way you would in Firefox.
Implementing the canvas element using VML poses a few problems (in addition to those that VML poses on its own). A canvas is a pixelmap. A VML figure, however, is a data structure. As long as you’re doing "shapes" you're fine, but if you start doing "pixels" - and lots of them - you get yourself into trouble quite rapidly. On a pixelmap you can keep painting the same spot over and over, and it'll still be "one pixel deep", if you know what I mean. On a VML figure, however, you just pile shapes on top of each other until IE explodes (Literally! Believe me, I've done it). Because of VMLs anti-aliasing feature IE needs to inspect all shapes underneath the last shape added to compute its proper color -- even if you don't use transparency. That's o(n2) if there ever was. You could, of course, optimise the figure by deleting all shapes that are completely obscured by a newly added non-transparent shape. I didn't do it, though. Only the clearRect function of my canvas implementation clears the figure by deleting shapes, but only if the full canvas is cleared (otherwise, more stuff is actually added). If you're doing animations you may want to clear the full canvas sooner rather than later.
A final note: I'm aware that whatever you do, someone on the vast expanses of the Internet will have done it already, so don't bother telling me. There are reasons why I don't (indeed, mustn't) even look too closely at stuff lying about on the Internet. To comfort anyone's hurt feelings (or rub salt in their wounds, whichever): It is a pretty obvious idea, once you inspect the canvas feature and also happen to know VML.