Javascript jQuery动画里面的递归函数非常慢
我有一个箭头在三张汽车图片上水平反弹的小动画。箭头从每次反弹200ms开始,每转一圈时间增加200ms,直到在3号车的第7圈停止 它在Chrome和Firefox上几乎可以顺利运行。在Safari 7上,它起步很快,两圈后速度变得很慢,跳过了很多帧 Javascript代码如下所示:Javascript jQuery动画里面的递归函数非常慢,javascript,jquery,html,Javascript,Jquery,Html,我有一个箭头在三张汽车图片上水平反弹的小动画。箭头从每次反弹200ms开始,每转一圈时间增加200ms,直到在3号车的第7圈停止 它在Chrome和Firefox上几乎可以顺利运行。在Safari 7上,它起步很快,两圈后速度变得很慢,跳过了很多帧 Javascript代码如下所示: var fwd = true; var cnt = 6; var time = 200; function play(){ var tgt = fwd ? '310px' : '10px'; $
var fwd = true;
var cnt = 6;
var time = 200;
function play(){
var tgt = fwd ? '310px' : '10px';
$('#arrow').animate({left: tgt}, time, function() {
if (cnt > 0){
cnt--;
fwd = !fwd;
time += 200;
play();
} else {
finalTarget();
}
});
}
function finalTarget (){
$('#arrow').animate({left: '230px'}, 466, function(){
$('#car3').hide(0).show('pulsate', {times: 3}, 600, function(){
$('#car1, #car2').fadeTo('slow', 0.3);
});
});
}
代码也在JSFIDLE上
这个代码有什么问题
我不应该在回调函数中调用“play”函数吗
编辑:
正如@jfriend00在注释中指出的,这段代码没有递归。“当调用动画完成函数并再次调用
play()
时,play()
的原始调用早已完成。”执行“循环”动画样式的典型方法是在回调中交替使用动画函数
我修改了你提供的小提琴:
Jquery:
cnt = 6;
var arrowSpeed = 400;
bounceLeft = function(){
$("#arrow").animate({left: "+=380px"},{duration:arrowSpeed, complete: bounceRight});
}
bounceRight = function(){
cnt--;
if(cnt>0){
$("#arrow").animate({left: "-=380px"},{duration:arrowSpeed, complete: bounceLeft});}else{
finalTarget();
}
}
bounceLeft();
function finalTarget (){
$('#arrow').animate({left: '230px'}, 466, function(){
$('#car3').hide(0).show('pulsate', {times: 3}, 600, function(){
$('#car1, #car2').fadeTo('slow', 0.3);
});
});
}
动画是一样的,但我认为我错误地判断了动画的宽度;还将其切换到“打开文档”。只需一个按钮即可轻松切换回“就绪”功能。您的代码需要大量重新绘制。如果您想要平滑的动画,请使用CSS关键帧…使其静音。这也是波涛汹涌吗@KevinB否。这在safari上运行平稳。@jon与
setTimeout(play,0)
@jon没有区别-动画完成函数(对play()
的连续调用源自此函数)本身已经由计时器调用,因此更改为setTimeout(play,0)
将不会解决任何问题,并会增加15毫秒左右的延迟。好的,这个实现比我的更好,但我在我的示例中也使用了回调,在您的示例中也使用了递归,但分两步进行。问题是,在Safari上的结果是一样的。从这个意义上说,回调是很奇怪的,我确实在每次完成时调用另一个函数,但这些都是不同的函数,您的回调调用的是封装动画和调用的函数;本质上,我猜[Play()开始->Animate()开始->Animate()结束->回调->Play()开始],因此你永远不会真正“完成”Play()调用,因此会产生开销。OP的代码不是递归的。当调用动画完成函数并再次调用play()
时,play()
的原始调用早已完成。正在从jQuery计时器调用play()
的连续调用。这不是递归的。通过读取代码,它看起来是递归的,但由于完成函数是异步的,并且在最初调用play()
完成后的某个时间发生,因此这不是递归,以这种方式调用本身不会导致任何资源的积累。@jfriend00是正确的。我从来没有这样想过,但我的代码和@Culyx的代码都不是递归的。play
函数在完成后被调用。我将编辑这个问题。@jfriend00解释得很好,仍然不确定性能上的差异是什么,也请编辑我的帖子