简体   繁体   English

如何在D3中重用两个(或更多)链式转换序列

[英]how to reuse two (or more) sequences of chained transitions in D3

I have to apply two very long sequences of chained transitions, which differ mainly on the order of transitions, and I'm looking for a compact way to code. 我必须应用两个很长的链式转换序列,它们主要区别于转换的顺序,我正在寻找一种紧凑的代码方式。

As a toy example, consider the case where the sequence orders should be a , b , c , d , e , f , g , h and e , f , g , h , a , b , c , d . 作为玩具示例,考虑序列顺序应为abcdefghefghabcd I've tried with the code below, but it doesn't work. 我已尝试使用下面的代码,但它不起作用。 Notice that the transitions could have different properties ( delay , duration , ease , and so on) and they could apply to different attributes ( x , y , width , height or cx , cy , r , and so on) and styles. 请注意,转换可能具有不同的属性( delaydurationease等),它们可以应用于不同的属性( xywidthheightcxcyr等)和样式。 For example, transition a could refer to width , transition b to height , transition c to x , transition d to y , transition e to transform attribute, transition f to color style, etcetera. 例如,转换a可以指width ,转换b指向height ,转换c指向x ,转换d指向y ,转换e指向transform属性,转换f指代color样式等。

PS: This question has the same aim of my previous one but there I used a too much simple coding case that misguided answers. PS:这个问题与我之前的问题具有相同的目的,但在那里我使用了太多简单的编码案例,误导了答案。

Is there any way to code this in a compact way? 有没有办法以紧凑的方式编码?

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); 

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. 每个函数都接受一个d3.selection对象,并将特定的转换参数和转换集应用于它。 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: 这里已经有一些代码重复,所以让我们将选择转换为转换,并使用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) }
};

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'] ); 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) ); } }) } 
 <script src="http://d3js.org/d3.v5.js"></script> <svg></svg> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM