2017-08-02 49 views
4

我有一个功能triggerWave(),它使画布上的点以波形形式生成动画。我正在使用d3.ease('quad-in')进行缓冲,我想用d3.timer()使triggerWave()函数调用超过200ms时间范围。我在找到d3.timer上的教程或例子时运气不佳。如何在d3 V3中使用计时器?

triggerWave() { 
    //function logic 
    let count = 0; 
    let xScale = d3.scale.linear().range([1,2]); // want the value to change from 1 to 2. 
    let zScale = d3.scale.linear().domain([0, 200]); // 200 ms. 
    let value = xScale(d3.ease('quad-in')(zScale(count))); 
    if(count < 200){ 
    count++; 
    d3.timer(() => triggerWave()); 
    } else { 
    // do something 
    } 
    this.wave.next({currentFrame: value}); 
} 

当我如上打电话d3.timer(),该triggerWave()函数被调用无限的时间和永不停歇。我想操纵或控制时间。在我的情况下,我想要为200ms触发定时器()。

如何理解如何使用d3.timer()函数?

+2

Tums,我写了一个答案,只有在发布之后,我注意到你正在使用D3 v3。不幸的是,在v3中没有'd3.timeout',但是你可以用我在vanilla JS的答案中提出的同样的方法,也就是'setTimeout':https://jsfiddle.net/gerardofurtado/ffv3r5gn/ –

回答

4

在版本3中,没有d3.timer.stop()功能。您必须在一定时间后返回true以停止计时器。

在赫拉尔多的回答中,他非常好地解释了如何使用d3 timeout这将是您的问题的有效解决方案,即一段时间内反复调用函数。但看看你对Gerardo的回答的评论,我想你正在寻找别的东西。

这就是我想出了,我认为这是你在找什么:

您可以创建一个称为activateTriggerWave()将在按钮上点击这个函数内部调用另一个函数,可以调用您的triggerWave()方法使用d3 timer

function activateTriggerWave() { 
    d3.timer(elapsed => { 
    this.triggerWave(); 
    if(elapsed >= 200){ 
    return true; // this will stop the d3 timer. 
    } 
}); 
} 

triggerWave() { 
// here you can do whatever logic you want to implement. 
} 

我希望这会有所帮助。

+1

好的答案,但。为什么打字稿? –

+0

@GerardoFurtado谢谢:)我一直在写太多的打字稿与Angular 4,我只是写了它,而没有看它是JS还是TS。 ;)将在编辑中添加一个JS版本。但我认为,只有类型转换和功能关键字才会被添加。不是吗? – ShellZero

4

编辑:我完全彻底无缘巨大,大“V3”,这是在那里,在问题的标题对不起,我会在这里继续这个答案作为参考V4的用户。)

由于您在triggerWave函数本身内部调用triggerWave,因此您不需要d3.timer,而是使用d3.timeout。按照APId3.timeout

如定时器,除了定时自动停止在其第一个回调。保证不会在后台运行的setTimeout的合适替代品。回调将通过经过的时间。

另外,请注意,每次函数运行时都会重置count,这是行不通的。设置其初始值外部的功能。

下面是演示了这些更改。我打电话的功能,每200毫秒,直到count到达50

var p = d3.select("p") 
 
var count = 0; 
 

 
triggerWave(); 
 

 
function triggerWave() { 
 
    p.html("Count is " + count) 
 
    if (count < 50) { 
 
    count++; 
 
    d3.timeout(triggerWave, 200) 
 
    } else { 
 
    return 
 
    } 
 
}
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<p></p>

您还可以通过d3.timeout保持的总时间轨迹,使用传递给triggerWave参数:

var p = d3.select("p") 
 
var count = 0; 
 
var elapsed = 0; 
 
var format = d3.format(".2") 
 

 
triggerWave(); 
 

 
function triggerWave(t) { 
 
    elapsed = t ? elapsed + t : elapsed; 
 
    p.html("Count is " + count + ", and the elapsed time is " + format(elapsed/1000) + " seconds") 
 
    if (count < 50) { 
 
    count++; 
 
    d3.timeout(triggerWave, 200) 
 
    } else { 
 
    return 
 
    } 
 
}
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<p></p>

由于您正在使用D3 v3,并且因为v3中没有d3.timeout,所以您可以使用vanilla JavaScript执行相同的操作:setTimeout

这里是一个演示:

var p = d3.select("p") 
 
var count = 0; 
 

 
triggerWave(); 
 

 
function triggerWave() { 
 
    p.html("Count is " + count) 
 
    if (count < 50) { 
 
    count++; 
 
    setTimeout(triggerWave, 200) 
 
    } else { 
 
    return 
 
    } 
 
}
<script src="https://d3js.org/d3.v3.min.js"></script> 
 
<p></p>

+0

Gerardo,非常感谢您的回答。在你的回答中你提到我在triggerWave函数本身中调用了我的函数triggerWave,因此我不需要d3.timer。我实际上是通过调用rAF(()=> triggerWave())中的triggerWave函数来实现使用requestAnimationFrame的动画。但是,我想用d3.timer来实现。那么,用d3.timer,我应该从外面调用这个函数吗?如果是的话,我该怎么做,以及如何在这种情况下停止功能。它进入了一个无限循环:( – Tums

+0

而且,我从同一个函数内部调用函数,因为'triggerWave'函数在点击按钮时被调用,也就是说,在按钮点击时,函数正在启动并且然后进行循环,我在里面使用了'd3.timer',并且一次又一次地调用函数。我不确定如何触发按钮上的'd3.timer'并将我的函数作为回调函数并使其返回true以阻止它。这就是我正在努力和无法找到资源在线。 – Tums