简体   繁体   English

使用setTimeout延迟d3转换

[英]Using setTimeout to delay d3 transition

I am trying to create a simple plane animation along a spiral curve 我试图沿着螺旋曲线创建一个简单的平面动画

However, I encountered issue when trying to delay the transition using d3's delay function, the animation does not seem to go correctly 但是,我在尝试使用d3的延迟功能延迟转换时遇到问题,动画似乎没有正确进行

So I have been contemplating using setTimeout to delay the triggering of the transition function, but could not seem to get it right. 所以我一直在考虑使用setTimeout来延迟触发转换函数,但似乎无法使其正确。 Could someone give me a suggestion? 有人可以给我一个建议吗?

Link to the fiddle . 链接到小提琴 This includes the original transition without setTimeout or any .delay; 这包括没有setTimeout或任何.delay的原始转换; v15 shows the error with using .delay; v15显示使用.delay的错误; and v16 has what I have tried with setTimeout 和v16有我用setTimeout尝试过的东西

This is my code for transitioning without setTimeout (which works fine without .delay) 这是我没有setTimeout进行转换的代码(没有.delay工作正常)

function transitionThis(d,i) {
d3.select(this).transition()
.duration(3000)
//.delay(3000) //causes error in the animation
.ease("exp")
.each("start", function() { d3.select(this).style("opacity", "1"); })    
  .attrTween("transform", translateAlong(path.node()))
  .styleTween("opacity", function () {return d3.interpolate("1", "0");});}

plane.each(transitionThis);

// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
  var l = path.getTotalLength();
    var t0 = 0;
    return function(i) {
  return function(t) {
    var p0 = path.getPointAtLength(t0 * l);//previous point
    var p = path.getPointAtLength(t * l);////current point
    var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle for tangent
    t0 = t;
  return "translate(" + p.x + "," + p.y +  ")scale(" + (0.2+t*4) + ")rotate(" + angle +"15"+")";
};
  };
}

and this is my attempt at adding setTimeout 这是我尝试添加setTimeout

function transitionThis(d,i) {
d3.select(this).transition()
.duration(3000)
//.delay(3000) //causes error in the animation
.ease("exp")
.each("start", function() { d3.select(this).style("opacity", "1"); })    
  .attrTween("transform", translateAlong(path.node()))
  .styleTween("opacity", function () {return d3.interpolate("1", "0");});
}

function delayedFlight() {
var tOut = setTimeout(transitionThis(),3000);
}
plane.each(delayedFlight);

Here's what's happening: for some reason, adding .delay() to the transition makes it so that every once in a while the interpolation function (the one that returns the transform value) gets called two times in a row with the same value of t . 这是正在发生的事情:由于某种原因,在转换中添加.delay()会使得每隔一段时间插值函数(返回转换值的函数)会连续两次调用t值相同的t For example, here's a subset of the output I got when I inserted console.log(t) : 例如,这是我插入console.log(t)时得到的输出的子集:

0.006692062648206693
0.006707542472169953
0.007238969233518517
0.007255714140926161
0.0077049430038543705
0.0077049430038543705 // <- same as previous
0.008568945153864268
0.008588766510821856
0.00899496468906235
0.00899496468906235   // <- same as previous
0.009529833123126597
0.00955187716946928
0.01107410052517391
0.011099716711945125
0.012516716837337842

I'm not why it happens, but technically it's not a bug, just a quirk. 我不是为什么会这样,但从技术上讲,这不是一个错误,只是一个怪癖。 However, it causes a sort of bug with your interpolation function: When t0 and t are equal, so are p0 and p and as a result the computed angle is 0 for those intermittent cases. 但是,它会导致插值函数出现一种错误:当t0t相等时, p0p也是如此,因此对于那些间歇性情况,计算angle为0。 And that's when you see the plane stutter – whenever its rotation is set to 0. 当你看到飞机断断续续时 - 只要它的旋转设置为0。

The easiest fix is to make it so that t0 and t are never equal, which can be achieved by intercepting that condition and modifying t0 a bit. 最简单的解决方法是使t0t永远不相等,这可以通过截取该条件并稍微修改t0来实现。 Like this: 像这样:

    // Happens every once in a while
    if (t == t0) {
        // Move t0 "back in time" a bit
        t0 -= .00001;
    }

It's not so pretty, but is probably still better than getting into setTimeouts.... 它不是那么漂亮,但可能仍然比进入setTimeouts更好....

Here's the modified fiddle 这是修改过的小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM