如何在d3.js中更改数据的函数调用之间添加延迟?

时间:2019-05-08 16:27:56

标签: javascript d3.js

我有一个函数my_fn,它可以更改某些元素的数据并进行转换。

我想在for循环中调用该函数,以便一次进行一次更改和过渡,并在它们之间短暂停留。

以下代码段可能无法单独运行,但显示了问题:

function updateData(){
  for (i=0; i<20; i++){
    my_fn();
    //console.log('sleeping...');
    //sleep(300);
  }
}

function my_fn(){

  var delay_amount = 300;

  focus.selectAll('circle')
    .transition()
    .delay(delay_amount)
    .attr('cy', function(d, i){
      if (d.index == 5){
        d.y += change_amount;
      }
      return y(d.y);
    });
}

我正在尝试使用d3的delay()函数进行过渡。但是,当我运行此命令时,它会暂停(延迟量),然后所有圆都立即移动。由此看来,my_fn会立即被调用20次,所有过渡都被延迟,然后它们都立即发生。

为解决此问题,我尝试在updateData()中添加注释的代码(具有仅在while循环中等待的睡眠功能)。这似乎要等待300毫秒的睡眠周期中的20个,然后立即进行所有转换。

这是怎么回事?我该如何实现?

NB:我见过this question,并且似乎在问类似的问题,但是答案似乎不起作用。我相信这是因为尽管不确定,但从selectAll调用了它们的“循环”。

1 个答案:

答案 0 :(得分:3)

您说对my_fn()的立即呼叫是正确的。 delay()调用对for循环没有影响,因此对my_fn()的所有20个调用都将立即调度。

要获得所需的效果,您必须使用回调,以便在上一个操作完成之前才进行对my_fn()的下一个调用。您可以像这样用d3做到这一点

function my_fn(){

  var delay_amount = 300;

  focus.selectAll('circle')
    .transition()
    .delay(delay_amount)
    .attr('cy', function(d, i){
      if (d.index == 5){
        d.y += change_amount;
      }
      return y(d.y);
    })
    .on('end', my_fn);
}

或者,如果您真的想使用for循环,则可以像下面这样使用setTimeout:

function updateData(){
  for (i=0; i<20; i++){
    setTimeout(my_fn, 300 * i);
  }
}

编辑

请注意,第一个示例将永远递归调用my_fn(),因此您需要实现某种逻辑以在第二十次调用之后停止。