D3 V4 - 画布过渡:d3.timer持续时间

时间:2016-09-04 17:10:46

标签: javascript animation d3.js html5-canvas d3v4

我跟着example here关于使用canvas元素的转换。 由于我使用的是d3版本4.2.2,我尝试移植示例但没有成功。 问题是(取决于d3.timer持续时间)动画停在一个点,点不在其正确的位置。它适用于 d3 v3 。以下是代码的一部分:

var duration = 1000;
var delay = function(d) {
  return d.i;
}
var maxDelay = 0;
var timeScale = d3.scaleLinear()
  .domain([0, duration])
  .range([0, 1]);

data.forEach(function(d) {
  d.trans = {
    i: d3.interpolateNumber(height, d.y),
    delay: delay(d)
  };
  if (d.trans.delay > maxDelay) {
    maxDelay = d.trans.delay;
  }
});

var renderTime = 0;
var timer = d3.timer(moveCircles);

function moveCircles(t) {
  data.forEach(function(d) {
    var time = timeScale(t - d.trans.delay);
    d.y = d.trans.i(time);
  });
  var start = new Date();
  drawCircles('black');
  var end = new Date();
  renderTime += (end - start);
  if (t >= duration + maxDelay) {
    console.log('Render time:', renderTime);
    timer.stop();
    return true;
  }
}

See this plunker获取完整示例。红点表示数据的正确位置(x / y)。因此,每个黑点应与一个红点重叠。点的y值越高,到其正确位置的距离越高。这导致我假设y值的插值存在误差?

有没有办法设置持续时间(例如1000)并为点s.t设置动画。在指定的持续时间后,每个点都处于正确的位置?

编辑:事实证明,使用与提供的示例中相同的easeCubicInOut,它可以正常工作。我不知道为什么会这样。

var ease = d3.easeCubicInOut;
...
function moveCircles(t) {
  data.forEach(function(d) {
    //var time = timeScale(t - d.trans.delay); // without the ease it won't work
    var time = ease(timeScale(t - d.trans.delay));
    d.y = d.trans.i(time);
  });
...

我怎样才能轻松自如?

1 个答案:

答案 0 :(得分:1)

不是直接的答案,因为我没有完成所有的计算,但这里有数学的东西:

var time = timeScale(t - d.trans.delay);
d.y = d.trans.i(time);

t - d.trans.delay需要生成介于0和1000之间的值,以便它在0到1之间缩放。显然,您正在提供的interpolate函数值大于1.我相信这样:

if (t >= duration + maxDelay) {

是罪魁祸首,因为你要将动画运行超过1000毫秒。

一种天真的方法就是限制它:

var time = timeScale(t - d.trans.delay);
if (time > 1) time = 1;
d.y = d.trans.i(time);

那就是说,我不确定这段代码是否需要如此复杂。一个基本的transition应该可以做你想做的事情:

d3.select({})
  .transition()
  .duration(duration)
  .tween("animate.circles", function() {
    return function(t) {
      data.forEach(function(d,i){
        d.y = d.trans.i(t);
      });
      drawCircles('black');
    };
});

更新了plunker