tic*_*tic 4 javascript transition d3.js
我必须应用两个很长的链式转换序列,它们主要区别于转换的顺序,我正在寻找一种紧凑的代码方式.
作为一个玩具例如,考虑顺序订单应该是这样的a
,b
,c
,d
,e
,f
,g
,h
和e
,f
,g
,h
,a
,b
,c
,d
.我已尝试使用下面的代码,但它不起作用.请注意,转换可能有不同的属性(delay
,duration
,ease
,等等),他们可以适用于不同的属性(x
,y
,width
,height
或cx
,cy
,r
,等)和样式.例如,转换a
可以参考width
,过渡b
到height
,过渡c
到x
,过渡d
到y
,过渡e
到transform
属性,过渡f
到color
风格,等等.
PS:这个问题与我之前的问题具有相同的目的,但在那里我使用了太多简单的编码案例,误导了答案.
有没有办法以紧凑的方式编码?
var t1 = d3
.transition() // transition "a" specifications
...
.transition() // transition "b" specifications
...
.transition() // transition "c" specifications
...
.transition() // transition "d" specifications
...
;
var t2 = d3
.transition() // transition "e" specifications
...
.transition() // transition "f" specifications
...
.transition() // transition "g" specifications
...
.transition() // transition "h" specifications
...
;
someelement1
.transition(t1).transition(t2);
someelement2
.transition(t2).transition(t1);
Run Code Online (Sandbox Code Playgroud)
如评论中所述,回答此问题的原则与您之前的问题相同.在这种情况下,您有一组不同的转换,可以按不同键引用的任何顺序应用.让我们将它们存储在一个对象中:
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) }
};
Run Code Online (Sandbox Code Playgroud)
每个函数都接受一个d3.selection
对象,并将特定的转换参数和转换集应用于它.这些功能可以随心所欲地变长和复杂.我很懒,想象力很少,所以他们只在这个版本中进行一次转换.
这里已经有一些代码重复,所以让我们将选择转换为转换,并使用this
而不是传递参数:
var transitions = {
a: function(){ return this.duration(1000).delay(1000).attr('cy', 200) },
b: function(){ return this.duration(2000).delay(0).attr('r', 40) },
c: function(){ return this.duration(500).delay(1500).attr('fill', 'red') },
d: function(){ return this.duration(1500).delay(500).attr('opacity', 0.5) },
e: function(){ return this.duration(1000).delay(3000).attr('cy', 300) },
f: function(){ return this.duration(2000).delay(0).attr('r', 60) },
g: function(){ return this.duration(500).delay(1500).attr('fill', 'magenta') },
h: function(){ return this.duration(1500).delay(500).attr('opacity', 0.25) }
};
Run Code Online (Sandbox Code Playgroud)
现在我们可以通过调用代码来执行这些转换
transitions['a'].call( selection.transition() )
transitions.f.call( d3.select('circle').transition() )
Run Code Online (Sandbox Code Playgroud)
您想要指定要应用于选择的过渡数组,如下所示:
apply_transitions( group.select(":nth-child(1)"), ['a','b','c','d'] );
apply_transitions( group.select(":nth-child(2)"), ['e','f','g','h'] );
Run Code Online (Sandbox Code Playgroud)
这可以实现如下:
/**
* 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) );
}
})
}
Run Code Online (Sandbox Code Playgroud)
实时动作示例:
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'] );
function apply_transitions( selection, tr_arr ) {
var transitions = {
a: function(){ return this.duration(1000).delay(1000).attr('cy', 200) },
b: function(){ return this.duration(2000).delay(0).attr('r', 40) },
c: function(){ return this.duration(500).delay(1500).attr('fill', 'red') },
d: function(){ return this.duration(1500).delay(500).attr('opacity', 0.5) },
e: function(){ return this.duration(1000).delay(3000).attr('cy', 300) },
f: function(){ return this.duration(2000).delay(0).attr('r', 60) },
g: function(){ return this.duration(500).delay(1500).attr('fill', 'magenta') },
h: function(){ return this.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) );
}
})
}
Run Code Online (Sandbox Code Playgroud)
<script src="http://d3js.org/d3.v5.js"></script>
<svg></svg>
Run Code Online (Sandbox Code Playgroud)