Jim's Depository

this code is not written

After piddling around with jQuery,CSS3, and the <canvas> tag for a week using only Safari 5 I decided to see how bad it was in Firefox. The comforting result was “not bad at all”.

Initially nothing rendered right, but that was all the first problem.

  • I was using a <base> with a relative URL, nice if you test in a subdirectory of your real server, but a mortal sin in the eyes of the W3C. Firefox caught me and ignored the directive.
  • My round corners and drop shadows were missing, but that is just because I didn’t add the -mozilla- variants. (I suppose I’ll make a CSS preprocessor to handle that as well as stripping my comments and white space.)
  • My @font-face fonts didn’t render in the <canvas> elements. The problem here is that there is no good way to tell a <canvas> tag to make sure it has the font loaded before it tries to get draw, and no way for your drawing code to check if the font is ready. (Safari can fail this race condition too, but it wasn’t happening to me so I didn’t notice it until I provoked it.)

    My solution is to defer any <canvas> drawing that uses text until after the $(window).load() fires. (Which you also can’t test for, and unlike .ready() won’t fire if the window is already loaded, so you have to add one to set your own ‘loaded’ flag.) This seems robust.

All in all I was pleasantly surprised. Two years ago the first browser change could be counted on to be a nightmare. Good work browser vendors!

The page in question looks like this:

  • Those meters are fully vector drawn in <canvas> at twice screen resolution to control pixelation artifacts and ensure a nice experience on \~300dpi devices. (\~12kbytes unminified and uncompressed, but that includes the pushbuttons and indicators as well which share code but aren’t on this page. Maybe 4k minified and compressed.)
  • The fonts are Droid and Molengo out of the Google Font Directory. A nice way to get some new fonts in play, but also have a high likelihood of a user already having them cached and serving them off a different hostname for more parallelism if not cached. (90k bytes)
  • I spent about an hour looking for a nice tileable brushed metal before giving up (after finding one only to discover the author didn’t know what tileable meant). I made this one in 5 minutes with gimp. (3.8k bytes)
  • Those meters also have color coding, but the sun is up and the batteries are full, so none of them are yellow or red.
  • Drawing the meters in <canvas> takes less bandwidth than sending images. For even a single meter, the code is smaller than the image would be, plus the code caches, so subsequent meter updates are nearly bandwidth free.
  • All told, the sources to that page are larger than the PNG screenshot, but the bulk of that is the fonts (90k) and jquery (22k). The uncached portion is 2.5k(800 on wire) for the index.html and 600 bytes for the AJAX query for the current data. Each of these comfortably fits in a single datagram.


power.png 113783 bytes
First fly in the ointment: The iPhone 4 renders these gorgeously when zoomed in. The over sampling is beautiful. And you get to look at it for a long time as it more or less freezes MobileSafari when you zoom way in. The refresh after a small pan can be 10 seconds. Double-tapping to get back to a wide zoom frees you from this hell after the next redraw.