禁用所有D3动画(用于测试)

时间:2013-01-21 17:09:23

标签: animation d3.js

我正在寻找相当于jQuery.fx.off = true的D3。

假设您正在为使用D3的应用编写测试(使用Mocha,QUnit等)。该应用有一些D3动画(.transition())。

动画真的不适合测试:

首先,它们很慢。

其次,因为它们是异步的,所以它们很容易导致闪烁测试。理想情况下,您需要避免拨打setTimeout / setInterval / requestAnimationFrame

有没有办法禁用所有D3动画,以便它们立即(理想情况下,同步)跳转到最终状态? (也许如果没有选项,我们可以挂钩timer.js?)

4 个答案:

答案 0 :(得分:13)

模拟转换的替代方法是将它们直接同步执行到它们的最终状态。

使用D3.js v4,使用:

function flushAllD3Transitions() {
    var now = performance.now;
    performance.now = function() { return Infinity; };
    d3.timerFlush();
    performance.now = now;
 }

使用D3.js v3和之前的命令,执行:

function flushAllD3Transitions() {
    var now = Date.now;
    Date.now = function() { return Infinity; };
    d3.timer.flush();
    Date.now = now;
 }

另见d3 issue 1789

答案 1 :(得分:5)

我不知道在d3中使用本机方式。但您可以通过增加d3原型来轻松修改d3选择器API以跳过动画:

要动画的HTML代码:

<svg width="200" height="200">
    <rect x="1" y="1" width="0" height="100" />
</svg>

动画和D3增强代码:

function animate(color){
    d3.selectAll("rect")
    .attr("width", 0).attr("fill", "white")
    .transition().duration(1000)
    .attr("width", 100).attr("fill", color)
}

function augment(){
    // add a duration function to the selection prototype
    d3.selection.prototype.duration   = function(){ return this }
    // hack the transition function of d3's select API
    d3.selection.prototype.transition = function(){ return this }
}

animate("red")
console.log("normal animation done")
setTimeout( function(){
        augment()
        console.log("d3 hacked!")
        animate("green")
        console.log("animation skipped")
}, 1200 )

注意!此黑客攻击可能无法为您提供完整的解决方案。您可能希望使用transition().*上未提供的以及您在应用程序中使用的其他d3.selection.prototype函数来扩展此解决方案。 您还可以考虑d3支持的其他形式的动画。也许我不了解<selection>.transition()以上。

答案 2 :(得分:2)

好像你可以模拟d3.timer函数:

var d3timer = d3.timer;

d3.timer = function(callback, delay, then) {
    d3timer(callback, 0, 0);
};

答案 3 :(得分:1)

您可以采取的一种方法是在测试套件中使用假计时器,例如Sinon,它可以与Mocha或QUnit配合使用。 Jasmine还有一个模拟计时器built in。我认为这是一种更好的方法,因为它意味着您正在测试的代码更接近正在运行的代码(而不是破坏转换函数)。