6

我有一个复杂的动画序列,涉及 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);
}

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

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

4

2 回答 2

13

几件事:

  1. 你的超时时间是 25 毫秒。这转换为 40fps,这是一个非常高的帧速率,可以尝试通过 javascript 实现。特别是对于涉及可能触发重排的 DOM 操作的事情。将其增加到 50 或 60。对于您正在制作的动画类型,15fps 应该足够流畅。您不是要在此处显示视频,而是在页面上移动内容。

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

    setTimeout(function(){
        pageFadeIn(0)
    },50);
    

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

  3. 正如 Ben 所提到的,使用单个 setTimeout 来安排功能更便宜。就此而言,代码清晰度可能会通过使用 setInterval 来提高(或者可能不会,取决于您的编码风格)。


补充回答:

Programming javascript animation is all about optimisation and compromise. It's possible to animate lots of things on the page with little slow-down but you need to know how to do it right and decide what to sacrifice. As an example of just how much can be animated at once is a demo real-time strategy game I wrote a couple of years ago.

Among the things I did to optimize the game are:

  1. The walking soldiers are made up of only two frames of animation and I simply toggle between the two images. But the effect is very convincing nonetheless. You don't need perfect animation, just one that looks convincing.

  2. I use a single setInterval for everything. It's cheaper CPU-wise and easier to manage. Just decide on a base frame rate and then schedule for different animation to start at different times.

于 2010-11-18T03:29:42.920 回答
3

好吧,那是很多 javascript(尽管“令人敬畏的四倍剂量”:)

您正在触发很多 setTimeout 序列,我不确定 JS 引擎对此进行了怎样的优化.. 特别是 IE <= 8

好的,也许只是一个粗略的建议……您也许可以编写一个小型计时引擎。

维护一个全局对象,该对象存储您当前正在运行的定时事件以及要运行的函数,以及延迟...

然后有一个单独的 setTimeout 处理程序来检查该全局对象,并减少每次迭代的延迟并在延迟变为 < 0 时调用该函数

你的全球事件看起来像这样:

var events = {

        fade1 : {
            fn : func_name,
            delay : 25,
            params : {}
        }

        fadeArrow : {
            fn : func_name,
            delay : 500,
            params : {}
        }

        slideArrow : {
            fn : func_name,
            delay : 500,
            params : {
                arrow:some_value
            }
        }

    }

然后创建一个函数以间隔(可能是 10 或 20 毫秒)循环遍历这些函数,并减少延迟,直到它们完成并使用 params 作为函数的参数触发函数(检查 Function.call )。

一旦关闭,再次以相同的延迟触发 setTimeout ..

要取消事件,只需从事件列表中取消设置属性..

构建一些方法来添加/删除排队事件,更新参数等等。

这会将所有内容减少到只有一个超时处理程序..

(只是一个想法)

于 2010-11-18T03:12:02.450 回答