Skip to content
  • Mike Bostock's avatar
    Transition reselection. · 223d6aa7
    Mike Bostock authored
    It is now possible to reselect elements with scheduled transitions and redefine
    associated tweens; this enables "post-selection" to customize the behavior of
    reusable components undergoing transitions, such as an axis. This commit also
    makes it much easier to sequence transitions.
    
    Previously, a transition's tweens were stored privately by the transition and
    could only be accessed through the transition. This made it impossible to modify
    transitions created by components: the transition is not accessible externally,
    and cannot be reselected from the document. Consider the following snippet:
    
      g.select(".x.axis")
          .call(xAxis)
        .selectAll("text")
          .attr("dy", null);
    
    If `g` is a selection, then this code alters the appearance of the axis as
    expected. However, if `g` is a transition, then transition.selectAll creates a
    new concurrent transition, and now multiple tweens compete to set the "dy"
    attribute. Oy!
    
    Under the new design, an element's scheduled tweens are stored semi-privately on
    the node (in the existing node.__transition__). Transition parameters can thus
    be reselected and modified by transitions that share the same id. If you now
    reselect a transitioning element, you modify the transition rather creating a
    competing transition; this should be less surprising and allow greater control.
    
    As a side-effect of this change, it is no longer possible to schedule concurrent
    transitions on the same element, even with the same id: only one transition may
    be active on a given element at any time. (Note that you can still schedule
    multiple future transitions on the same element, and concurrent transitions on
    different elements.) For example, you could previously schedule overlapping
    transitions with different easing functions, delays or durations, provided you
    were careful to avoid conflict. This seems like a relatively obscure use-case
    compared to modifying a transition, so I believe this is a reasonable change.
    
    This commit also changes transition.transition, such that the returned
    transition starts at the end of the originating transition, rather than
    overlapping. This makes it much easier to schedule sequenced transitions without
    the complexity of transition.each("end") and d3.select(this).
    
    Also, transitions are now simply arrays of nodes, consistent with selections!
    223d6aa7