Zoom Transitions

Example: http://bl.ocks.org/mbostock/06ecebbae5be9665e995

My biggest concern is dispatching zoom events on the initial application of the zoom behavior. This could easily break old code because the listener may not be ready to receive zoom events at the time the behavior is applied.

For example, it is common to apply the zoom behavior to a parent element that contains elements (such as axes) whose appearance will change during zoom. If the zoom behavior dispatches zoom events on its initial render, those child elements will not yet exist and the listener will crash. It’s easy to workaround this problem by registering the zoom behavior _after_ creating those child elements (per the above example), but this change would still break old code.

(The same argument applies to the brush on its initial render, though I think it will be less common for those brush events to break anything because commonly the brush is drawn on top of (and thus after) elements that are affected by the brush state.)

On the other hand, one nice side-effect of the zoom behavior dispatching zoom events on initial application is that you eliminate code duplication between enter (the initial display) and update (in response to subsequent user events). But this is a negligible benefit as you could just as easily eliminate that code duplication by calling the zoom event listener explicitly on enter.

Potential fixes:

1. We could defer dispatch of events on application one tick by using d3.timer. This would guarantee that child elements have been created, however it is undesirable because it would cause flickering on the initial display.
2. We could not emit zoom events (and likewise brush events) when the zoom behavior is initially applied (and likewise whenever the brush is applied via selection.call). However, this would arguably be inconsistent with the automatic emission of events during transitions, and would require the caller to do more work during initialization.
3. We could special-case just the first application of the zoom behavior (and likewise the brush) to not emit events. But, this feels like an overly specialized fix.