I don't know if I should be proud that I accomplished something, or horrified at how long it took and how complex modern interactive web programming is today (or perhaps how atrophied my programming brain has become). In any case, I wanted 100% control over the interaction, and I finally got what I wanted - but it was hard. I could have done this in Java or in iOS much, much, much faster (well, at least if I had a graph layout algorithm handy).
Anyway, here is a high-level summary of what I learned:
- Interactive Graphics Layer: HTML5 "canvas" v. "svg". First exploration was to analyze canvas (pixel-based write-only renderer) v. SVG (DOM-based, animatable, eventable vector graphics). SVG is much closer to my beloved Pad++ & Piccolo days of yore - and scalable and interactive is what I need. So, SVG it is.
- JavaScript SVG Wrapper: SVG is ugly, and not meant for humans to write. So, I went looking for a library. I found 3:
- D3: Advanced. Written by the brilliant and experienced Mike Bostock. High level, focused on data bound visualizations. A slight impedance mismatch for what I am looking for - but in the end, the clear winner (more below)
- Raphael: Low-level and multi-platform compatible. Meaning it supports the least common denominator of features across all browsers (including IE's VML). This means no groups and no classes. No groups means it is very difficult to hang data off a collection of items in the DOM - and so you are obligated to create a shadow data structure in the app. No classes means no easy styling, and no generic event handlers.
- JQuery SVG Plugin: This is actually about the feature set I was initially looking for, but the tool just isn't sophisticated enough. The architecture isn't clean enough, the docs and examples aren't sufficient, and I didn't have confidence that this project has legs. Close though - and with some TLC, it could become great.
- D3: D3 is well known to have a high learning curve - and it does. There are a handful of issues, some of which could definitely be helped by more documentation. It took me about a solid week to really feel comfortable with it - although admittedly that included brushing up on my JavaScript and DOM knowledge. However, I bet I'm not that atypical here. Anyway, here are a few issues I ran into:
- The basic data binding model (w/ "enter" and "exit" mechanisms for more and fewer bound data items) just takes a while to wrap your head around. The docs here are good - just new to me.
- The relationship between D3 selection and underlying objects took a while to get a handle on. When you get a selection, are those DOM objects, and if not, what are they? This should be spelled out really clearly in the docs.
- Guidance on use with JQuery. Turns out this wasn't hard, but I (like just about everyone I know) rely on JQuery - so what are the catches? When is it a good idea to use D3 v. JQuery binding? Are they interchangable? Can you even use JQuery to select SVG DOM elements? A section on this in the docs would be really helpful.
- Events bound to selections are *statically* bound. This is the same as JQuery, and I should have known better - but it really threw me for a loop. This means that when you bind an event to a class name, and then change the class name - the event handler doesn't get unbound. You have to manually unbind and then bind new event handlers.
- Knowing what is a DOM attribute and what is a CSS style is confusing. A summary table of supported SVG objects, attributes and styles would be really helpful.
- I kept on wanting to write event handlers that worked on only some elements of a selection, but couldn't figure out how. For example, I would have a bunch of active nodes, and want to act on all of them except the one the mouse was over. With 20 years of iterative programming in my brain, I spent an inordinate amount of time before I realized that in this new world of selection-based programming, the right approach was to change "class" tags on the elements so just the things I wanted had the right class names - and then select on that class.
- Finally, the D3 API docs are pretty good, but badly need complete examples. Many have no examples, and hunting through the demos to see how something is actually used is very time consuming. And where there are examples, they are usually abstracted. That is fine for conceptual understanding, but I kept wishing they were linked to full, simple standalone examples. For example, I spent 3 hours getting the syntax of a path right - and then figured out later I could have just created a line. Sigh...
Well, there's more - but that's a start. Modern web graphics technology is amazing. I'm heading out of the country for a few weeks, but when I return, I expect to be able to start building cool stuff!
Yay, great blog post! I totally agree with you about D3's learning curve and documentation. The flip side to the lack of complete reference examples is there's a lot of real world examples of complex visualizations. It's not all well organized, though.
ReplyDeleteThe best guide I've seen to SVG and the myriad DOM and CSS attributes is the SVG spec itself. It's surprisingly readable. The MDN docs for SVG are also good.
Website designers in Perth are focusing on interactive websites now. I am interested to know how to create one but it seems that I have to master the basics first because the D3 experiments that you've worked on seems complicated. Anyway, I like the breakdown of the results of the experiments that you shared because it helps the people to be aware of the possible problem that they may experience if they try this too.
ReplyDelete