Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/454.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript D3 V4-画布转换:D3.4计时器持续时间_Javascript_Animation_Html5 Canvas_D3.js - Fatal编程技术网

Javascript D3 V4-画布转换:D3.4计时器持续时间

Javascript D3 V4-画布转换:D3.4计时器持续时间,javascript,animation,html5-canvas,d3.js,Javascript,Animation,Html5 Canvas,D3.js,我遵循了关于画布元素的转换。 因为我使用的是d3版本4.2.2,所以我尝试移植这个示例,但没有成功。 问题在于(取决于d3.timer持续时间),动画会在点不在其正确位置的点停止。它可以与D3V3配合使用。以下是代码的一部分: var duration = 1000; var delay = function(d) { return d.i; } var maxDelay = 0; var timeScale = d3.scaleLinear() .domain([0, duration

我遵循了关于画布元素的转换。 因为我使用的是d3版本4.2.2,所以我尝试移植这个示例,但没有成功。 问题在于(取决于
d3.timer
持续时间),动画会在点不在其正确位置的点停止。它可以与D3V3配合使用。以下是代码的一部分:

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;
  }
}
举个完整的例子。红点表示数据的正确位置(x/y)。因此,每个黑点都应该与一个红点重叠。点的y值越高,到其正确位置的距离就越大。这导致我假设y值的插值存在错误

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

EDIT:结果表明,使用与所提供示例相同的
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);
  });
...

我怎么能跳过这个问题呢?

这不是一个直接的答案,因为我没有完成所有的计算,但这里的数学有点问题:

var time = timeScale(t - d.trans.delay);
d.y = d.trans.i(time);
t-d.trans.delay
需要生成一个介于0和1000之间的值,以便它在0到1之间进行缩放。显然,您正在输入大于1的
插值
函数值。我相信:

if (t >= duration + maxDelay) {
是罪魁祸首,因为您将在1000毫秒后运行动画

一种幼稚的做法是将其封顶:

var time = timeScale(t - d.trans.delay);
if (time > 1) time = 1;
d.y = d.trans.i(time);
也就是说,我不确定这段代码是否需要如此复杂。一个基本的学生应该能够做你想要做的事情:

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');
    };
});

更新。

非常感谢您的努力。我真的很讨厌你,你的小玩意儿太棒了!问题在于,afaik转换在数据点的数量上是不可伸缩的(或者有解决方法吗?),这基本上是我使用画布而不是svg的意图之一。例如,如果更改
size=10000
,则过渡不再平滑。