如何在D3中重用两个(或更多)链接转换序列 [英] how to reuse two (or more) sequences of chained transitions in D3

查看:71
本文介绍了如何在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.

作为一个玩具示例,请考虑以下情况:顺序顺序应为abcdefghefghabcd.我已经尝试使用下面的代码,但是它不起作用.请注意,过渡可能具有不同的属性(delaydurationease等),并且它们可以应用于不同的属性(xywidthheightcxcyr等)和样式.例如,过渡a可以引用width,过渡bheight,过渡cx,过渡dy,过渡etransform属性,将f转换为color样式等.

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. 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. 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.

PS:此问题与我的上一个目标相同一个,但是在那里我使用了太多简单的编码案例,误导了答案.

P.S.: This question has the same aim of my previous one but there I used a too much simple coding case that misguided answers.

有没有办法以紧凑的方式编写代码?

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

每个函数都使用一个d3.selection对象,并对其应用特定的过渡参数和转换集.这些功能可能会很长而且很复杂.我很懒惰,几乎没有想象力,所以他们在这个版本中只做一次转换.

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.

这里已经有一些代码重复,因此让我们将选择内容转换为过渡内容,并使用this而不是传递参数:

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(){ 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) );
      }
    })
}

实况示例:

    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>

这篇关于如何在D3中重用两个(或更多)链接转换序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆