How To Reuse Two (or More) Sequences Of Chained Transitions In D3
Solution 1:
As noted in the comments, the principles for answering this question are the same as your previous question. In this case, you have a set of different transitions that might be applied in any order referred to by different keys. Let's store them in an object:
var transitions = {
a: function(sel){ return sel.transition().duration(1000).delay(1000).attr('cy', 200) },
b: function(sel){ return sel.transition().duration(2000).delay(0).attr('r', 40) },
c: function(sel){ return sel.transition().duration(500).delay(1500).attr('fill', 'red') },
d: function(sel){ return sel.transition().duration(1500).delay(500).attr('opacity', 0.5) },
e: function(sel){ return sel.transition().duration(1000).delay(3000).attr('cy', 300) },
f: function(sel){ return sel.transition().duration(2000).delay(0).attr('r', 60) },
g: function(sel){ return sel.transition().duration(500).delay(1500).attr('fill', 'magenta') },
h: function(sel){ return sel.transition().duration(1500).delay(500).attr('opacity', 0.25) }
};
Each function takes a d3.selection
object and applies specific transition parameters and sets of transformations to it. These functions can be as long and complicated as you like. I am lazy with little imagination so they only do one transformation in this version.
There's already a bit of code repetition here, so let's take out the conversion of the selection to a transition, and use this
instead of passing an argument:
var transitions = {
a: function(){ returnthis.duration(1000).delay(1000).attr('cy', 200) },
b: function(){ returnthis.duration(2000).delay(0).attr('r', 40) },
c: function(){ returnthis.duration(500).delay(1500).attr('fill', 'red') },
d: function(){ returnthis.duration(1500).delay(500).attr('opacity', 0.5) },
e: function(){ returnthis.duration(1000).delay(3000).attr('cy', 300) },
f: function(){ returnthis.duration(2000).delay(0).attr('r', 60) },
g: function(){ returnthis.duration(500).delay(1500).attr('fill', 'magenta') },
h: function(){ returnthis.duration(1500).delay(500).attr('opacity', 0.25) }
};
Now we can perform these transitions by calling code like
transitions['a'].call( selection.transition() )
transitions.f.call( d3.select('circle').transition() )
You want to specify an array of transitions to apply to a selection, something like this:
apply_transitions( group.select(":nth-child(1)"), ['a','b','c','d'] );
apply_transitions( group.select(":nth-child(2)"), ['e','f','g','h'] );
This could be implemented as follows:
/**
* apply a series of transitions to a selection
*
* @param selection - d3 selection
* @param tr_arr - array of transition identifiers, referring to functions in the `transitions` object
*/
function apply_transitions( selection, tr_arr ) {
// turn the current selection into a d3.transition// call the transition function referred to by the first ID in the array// with the d3.transition as the `this` context// note that the function returns a transition object, so it can be chained
transitions[ tr_arr[0] ].call( selection.transition() )
// add a handler to be applied at the end of the transition.on('end', function(){
// if there are more transitions to be applied, call// apply_transitions again with tr_arr minus the first element// note that the `this` context in the `on` function is a DOM element,// so use `d3.select(this)` to turn it into a d3 selection
if ( tr_arr.length > 1 ) {
apply_transitions( d3.select(this), tr_arr.slice(1) );
}
})
}
Live action example:
var svg = d3.select('svg').attr('width', 500).attr('height', 500);
var dataSet = [20, 20];
var group=svg.append("g");
var circles = group.selectAll('circle')
.data(dataSet)
.enter()
.append('circle')
.attr("r",function(d){ return d })
.attr("cx",function(d, i){ return i * 100 + 50 })
.attr("cy",50)
.attr("fill",'black');
apply_transitions( group.select(":nth-child(1)"), ['a','b','c','d'] );
apply_transitions( group.select(":nth-child(2)"), ['e','f','g','h'] );
functionapply_transitions( selection, tr_arr ) {
var transitions = {
a: function(){ returnthis.duration(1000).delay(1000).attr('cy', 200) },
b: function(){ returnthis.duration(2000).delay(0).attr('r', 40) },
c: function(){ returnthis.duration(500).delay(1500).attr('fill', 'red') },
d: function(){ returnthis.duration(1500).delay(500).attr('opacity', 0.5) },
e: function(){ returnthis.duration(1000).delay(3000).attr('cy', 300) },
f: function(){ returnthis.duration(2000).delay(0).attr('r', 60) },
g: function(){ returnthis.duration(500).delay(1500).attr('fill', 'magenta') },
h: function(){ returnthis.duration(1500).delay(500).attr('opacity', 0.25) }
};
transitions[ tr_arr[0] ].call( selection.transition() )
.on('end', function(){
if ( tr_arr.length > 1 ) {
apply_transitions( d3.select(this), tr_arr.slice(1) );
}
})
}
<scriptsrc="http://d3js.org/d3.v5.js"></script><svg></svg>
Post a Comment for "How To Reuse Two (or More) Sequences Of Chained Transitions In D3"