Vector graphics in the browser

I've taken a look at the state of vector graphics in the browser.

Since the beginning of the web, people have been using GIFs to display their headline texts; tables and CSS to do layout; and GIFs for rounded corners etc. A lot of this would become a lot simpler if the browser was able to display vector graphics.

There are numerous systems for displaying vector graphics but the two I looked at in detail were the <canvas> tag and DOJO. Initially I realized that the <canvas> tag could not plot text, and I thought the DOJO system could. But it turns out it can't either. So I concentrated on the <canvas> tag.

The <canvas> tag, which works on Firefox, Safari and Opera, and a 1-line Javascipt include of excanvas, also works on Internet Explorer. It works well for trivially simple things. But there are a few things that don't work like I expected.

No callback for painting

Essentially a <canvas> is just a bitmap (like an <img>) which you can draw into programmatically using Javascript. This contrasts to traditional vector programming, where you register some kind of callback, and the system calls you when it needs the part of the window under your control to be redrawn.

The traditional way is certainly more complex, but it has a few advantages. If you are doing any kind of document editing, e.g. you are programming Word, then documents get big. But only a small amount is displayed on the screen at once. This gets more marked if you zoom in to 500%. With the callback mechanism, your application only get asked to draw the small part of the window on display. With the <canvas> approach, you have to draw everything, all the time. Imagine a grid which needs to draw lines every 5 pixels. That's a lot of lines on a 1,000 x 1,000 pixel screen; but it's a lot more if you need to draw everything in a 10,000 x 100,000 pixel workspace that the user could scroll around on.

It simply takes too long to draw everything the user could possibly see if you have a large workspace, or view a large document at a higher zoom. On a 5k x 5k pixel <canvas> with such a grid, Firefox complains "script seems to be unresponsive", whereas on a 1k x 1k grid (which is all you can see) it works fine.

Large <canvas> takes up lots of memory

As a <canvas> is just a bitmap, if you create a large one, a large amount of memory is immediately allocated. So if you are programming a Word using this technique, and the user scales the document to 500%, immediately their computer will slow down as the browser needs to allocate a huge amount of memory just to store all the pixels the user could potentially scroll around to see. And the Internet Explorer control and the Opera <canvas> seem to have a limit somewhere around 5k pixels.

You can't draw text

This is surely the most amazing limitation. Look at all the vector graphics examples in the web and you'll see e.g. beautiful clock examples – but they use a JPEG as the background to the clock including the numbers. That's hardly the way I had imagined vector graphics would be used!

But there is a "solution", as we see in this nice windowing example. As the browser can already display text, and the background to a <canvas> is transparent, you can layer one <canvas> on top of another, and put <div> objects inbetween.

If one is to display e.g. a Word document, with various vector graphics and various pieces of text, one would have to create lots of <canvas>es and lots of <div>s and absolute-position them on top of one another. That seems to me like a lot of programming work to create this structure, and to maintain it. And it can't be easy or quick for the browser to render such a document.

There is a solution in sight though. There will be a <canvas> drawText command in Firefox 3. Currently nobody has Firefox 3 and none of the other browsers support it. But that will no doubt be different in a few years time.

There is no way to query text metrics

If you want to have vector graphics and text on the same page, you need a way to find out the size of text in pixels. For example you want to center text on the screen. Or fit text into a weirdly shaped object. Thankfully this is supported with the Firefox 3 drawText command.

Zooming doesn't work on Opera

Maybe this is just an implementation issue, but as the vector graphics are turned into a bitmap at the time the Javascript commands to draw into the canvas are executed, if you say "scale to 200%" in Opera, it scales the generated bitmap, as opposed to scaling the original vectors and re-rendering them.

I always object to the name SVG on the grounds that it stands for "Scalable Vector Graphics", and vector graphics are scalable by their nature, so I don't understand why the file format wasn't just called VG. But it seems someone has indeed managed to implement what I thought was impossible: "non scalar vector graphics".

Conclusion

So what is one to do to implement a client-side app manipulating vector-based documents? It is clearly the way of the future.

As far as I can see, it's still not very easy. Which may explain why there are none of them around. The only one I can think of is Gliffy – and that's written in Flash.

The code to display a document is going to have to be quite tightly coupled with the display system (create and maintain <canvas> and <div>s). And for making modifications, I'm not sure if it's going to look nice to delete those <canvas> and <div>s and recreate them each time, maybe one is actually going to have to modify them e.g. during a drag operation, which will make the code particularly front-end specific.

P.S. I recently created a nerdy privacy-respecting tool called When Will I Run Out Of Money? It's available for free if you want to check it out.

This article is © Adrian Smith.
It was originally published on 22 Nov 2007
More on: Web | Graphics Algorithms