Create a transition template for re-use

Viewed 34

In D3 I have a transition like this

this.xAxis
    .transition()
    .ease(d3.easeBackInOut)
    .duration(1000)
    .call(this.xTicks)
    .attr('transform', `translate(0, ${this.height})`);

I am using the same transition in a few places.

Is there a way to make this into a function or something I can update it in one place like

transition(){
    .transition()
    .ease(d3.easeBackInOut)
    .duration(1000) 
}

this.xAxis
    transition()
    .call(this.xTicks)
    .attr('transform', `translate(0, ${this.height})`);
2 Answers

The most obvious answer to your question would be using a transition instance as the name of the transition:

selection.transition([name])

According to the API...

If the name is a transition instance, the returned transition has the same id and name as the specified transition.

However, the same API says:

If a transition with the same id already exists on a selected element, the existing transition is returned for that element. Otherwise, the timing of the returned transition is inherited from the existing transition of the same id on the nearest ancestor of each selected element.

Because of that, I don't think you want a named transition. So, my solution here is just extending the prototype, creating a function that gets the selection (this) and returns a transition with the desired methods:

d3.selection.prototype.transitionTemplate = function() {
  return this.transition()
    .ease(d3.easeBackInOut)
    .duration(1000);
};

Here is a demo:

d3.selection.prototype.transitionTemplate = function() {
  return this.transition()
    .ease(d3.easeBackInOut)
    .duration(2000);
};

d3.select("circle")
  .transitionTemplate()
  .attr("cx", 50)
  .attr("cy", 130);

d3.select("rect")
  .transitionTemplate()
  .attr("width", 100);
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg>
  <circle r="5" cx="10" cy="10" fill="teal"></circle>
  <rect x="100" y="50" height="50" width="20" fill="tan"></rect>
</svg>

You can make use of transition.call() which

Invokes the specified function exactly once, passing in this transition along with any optional arguments.

You can then create a function getting passed to .call() which configures the transition object passed into that function. You could even provide additional parameters to fine-tune configuration of your transition. As .call returns the transition it is called upon this approach fits neatly into the usual D3 method chaining syntax:

function configureTransition(transition) {
  transition
    .ease(d3.easeBackInOut)
    .duration(1000);
}

this.xAxis
  .transition()                // Create a transition on a selection.
  .call(configureTransition)   // Pass the function to configure the transition.
  .call(this.xTicks)
  .attr('transform', `translate(0, ${this.height})`);
Related