hgweb viewer, canvas version
If you want to go drawing complex graphics on the web, you have two basic options: SVG and the HTML canvas element.
My first attempt at the hgweb graphical browser used SVG. Actually, it used an unholy hybrid of SVG and HTML: the revisions themselves were drawn using absolutely positioned HTML. The arrows between the boxes were drawn using SVG. I did this for several reasons:
- only Firefox supports drawing text into canvas elements
- I could use DOM events to do hit-testing and navigation
- you can select/copy/paste text in HTML
Unfortunately, the performance of the first version was not very good, and the code was very complex. I was maintaining several parallel data structures: a JS object graph, and the DOM objects for revisions and arrows. The bookkeeping code to keep data in sync was dwarfing the actual layout logic.
Instead I decided to try using canvas. Sucking out the bookkeeping code and replacing it with a custom drawing code turned out to be much easier than I expected. Now all of the data is kept in a single tree, and layout, rendering, and hit-testing are all blazingly fast.
After getting it basically working, I was able to add additional features in a matter of minutes:
- Collision detection
- Animation when navigating between revisions
- Switched to a vertical layout which provides more information
- Made arrows into curves
- Highlight the “center” node
The disadvantages of this approach are unfortunate:
- Only works in Firefox 3+ (needs the experimental mozDrawText API)
- Impossible to select or copy text
check it out (my development machine, so it may go down at any time) or get the source.
Now I really promise I don’t have any more time to spend on this project. Contributions welcome!
April 16th, 2008 at 9:23 am
Wow, that’s pretty awesome… and yep, you’ve hit upon one of the main problems with SVG — unless your entire app is essentially a SVG document, doing graphics by doing DOM manipulation is pretty painful despite the added benefits (automatic hit testing, mainly). I bet someone could create a minimal hit testing infrastructure to work in conjunction with canvas to fix that problem.
You can work around the impossible to copy text problem by doing tinderbox-style dhtml popup when you click on a node; that could be a normal div, possibly with some added info to justify its existence, and selectable text.