为什么多个setTimeout()调用导致如此多的延迟?

Nie*_*sol 6 javascript firefox google-chrome lag

我有一个复杂的动画序列,涉及JavaScript中的淡入淡出和过渡.在此序列中,由四个元素一次变化组成,setTimeout在每个元素上使用a .

在Internet Explorer 9中测试,动画以实时速度运行(它应该需要1.6秒,并且需要1.6秒).任何其他浏览器都会出现可怕的延迟,动画时间为4秒(Firefox 3和4,Chrome,Opera)以及IE 8及以下版本的20秒.

当所有其他浏览器陷入泥潭时,IE9怎么能这么快?

我试图找到将元素合并为一个的方法,以便在任何给定时间都有一个setTimeout,但遗憾的是它不会经受任何干扰(例如点击不同的链接以在之前启动新的动画目前已完成).

编辑:为了回应评论,这里是代码的大纲:

link.onclick = function() {
    clearTimeout(colourFadeTimeout);
    colourFadeTimeout = setTimeout("colourFade(0);",25);

    clearTimeout(arrowScrollTimeout);
    arrowScrollTimeout = setTimeout("arrowScroll(0);",25);

    clearTimeout(pageFadeOutTimeout);
    pageFadeOutTimeout = setTimeout("pageFadeOut(0);",25);

    clearTimeout(pageFadeInTimeout);
    pageFadeInTimeout = setTimeout("pageFadeIn(0);",25);
}
Run Code Online (Sandbox Code Playgroud)

四个函数中的每一个都将淡入淡出一帧,然后在参数递增的情况下设置另一个超时,直到动画结束.

您可以在http://adamhaskell.net/cw/index.html(用户名:knockknock;密码:goaway)看到该页面(它有声音和音乐,可以禁用,但要注意!) - 我的JavaScript非常凌乱,因为我没有真正组织它,但它有点评论,所以希望你可以看到一般的想法是什么.

sle*_*man 13

几件事:

  1. 你的超时是25ms.这转换为40fps,这是一个非常高的帧速率,试图通过JavaScript实现.特别是对于涉及DOM操作的事物,可能会引发回流.将它增加到50或60.对于你正在做的各种动画,15fps应该足够流畅.你不是试图在这里显示视频,只是在页面上移动东西.

  2. 不要使用字符串作为第一个参数setTimeout().特别是如果你关心表现.这将强制javascript重新编译每帧动画的字符串.请改用功能.如果需要传递参数,请使用匿名函数来包装要执行的函数:

    setTimeout(function(){
        pageFadeIn(0)
    },50);
    
    Run Code Online (Sandbox Code Playgroud)

    这只会在加载脚本时编译一次.

  3. 正如Ben所提到的,使用单个setTimeout来调度函数会更便宜.就此而言,代码清晰度可以通过使用setInterval来改进(或者它可能不会,取决于您的编码风格).


补充答案:

编程javascript动画是关于优化和妥协的.可以在页面上制作很多东西,但速度很慢,但你需要知道如何正确地做,并决定要牺牲什么.作为一个可以立刻动画多少的一个例子是我几年前写的一个演示即时战略游戏.

我为优化游戏所做的事情包括:

  1. 步行士兵只有两帧动画,我只是在两幅图像之间切换.但是效果非常令人信服.你不需要完美的动画,只需要一个看起来令人信服的动画.

  2. 我使用一个setInterval来处理所有事情.它的CPU更便宜,更易于管理.只需确定基本帧速率,然后安排不同的动画在不同的时间开始.

  • @slebetman你答案的链接不再可用了.如果你还有它,你可以重新发布你的来源吗? (4认同)