Отключение всех анимаций D3 (для тестирования)
Я ищу эквивалент D3 для jQuery.fx.off = true
.
Скажите, что вы пишете тесты (с Mocha, QUnit и т.д.) для приложения, которое использует D3. В приложении есть несколько анимаций D3 (с .transition()
).
Анимация действительно плохо для тестов:
Во-первых, они медленны.
Во-вторых, поскольку они асинхронны, они могут легко вызвать мерцающие тесты. В идеале вы бы хотели избежать любых вызовов setTimeout
/setInterval
/requestAnimationFrame
.
Есть ли способ отключить все анимации D3, чтобы они мгновенно (и в идеале, синхронно) переходили в конечное состояние? (Возможно, если нет возможности, мы можем подключиться к timer.js?)
Ответы
Ответ 1
Альтернативой издевательствам переходов является их синхронно синхронизировать с их конечным состоянием.
С D3.js v4 используйте:
function flushAllD3Transitions() {
var now = performance.now;
performance.now = function() { return Infinity; };
d3.timerFlush();
performance.now = now;
}
С D3.js v3 и предыдущим, do:
function flushAllD3Transitions() {
var now = Date.now;
Date.now = function() { return Infinity; };
d3.timer.flush();
Date.now = now;
}
См. также d3 issue 1789.
Ответ 2
Я не знаю, как это сделать в d3. Но вы можете легко изменить API-селектор d3, чтобы пропустить анимацию, добавив прототипы d3:
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 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()
, о котором я не знаю.
Ответ 3
Один из подходов, который вы можете предпринять, - использовать поддельный таймер в вашем тестовом пакете, например Sinon, который работает с Mocha или QUnit. Жасмин также имеет макет таймера встроенный. Я думаю, что это лучший подход, потому что это означает, что код, который вы тестируете, ближе к текущему коду (в отличие от саботажа функций перехода).
Ответ 4
Похоже, вы можете издеваться над функцией d3.timer:
var d3timer = d3.timer;
d3.timer = function(callback, delay, then) {
d3timer(callback, 0, 0);
};