2017-08-02 48 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