35

我有一些元素在页面上移动得非常缓慢。本质上,我在 40 秒左右的时间内减少了两个图像的左边距。

从视觉上看,它工作得很好。但是,我的处理器在动画期间的使用率跃升至 50% 左右。这也不是特定于任何单一浏览器的——在 Safari3 和 Firefox3 上也是如此。如果我让两个浏览器都运行该页面,我的 CPU 会以大约 95% 的使用率尖叫。

我正在使用 jQuery 1.3。两个动画同时发生。页面上没有 Flash。如果我将代码注释掉(删除动画)并刷新页面,我的处理器会立即恢复正常使用。

我希望我不必求助于 Flash,但即使在 Hulu.com 上观看节目也不会像这样占用我的 CPU。

想法?

4

7 回答 7

44

我知道这是一个老问题,蒂姆提供了一个很好的答案,但我只是想我应该为任何寻求解决这个问题的人发布更新,因为现在有一种更简单的方法......

jQuery 1.4.3开始,您可以直接通过jQuery.fx.interval属性设置 jQuery 的动画使用的间隔。因此,您可以简单地执行以下操作:

jQuery.fx.interval = 50;
于 2010-12-08T21:43:30.260 回答
34

我认为 jQuery animate() 的工作方式是它使用一个计时器,该计时器定期触发并调用一个更新 DOM 以反映动画状态的函数。通常动画相对较短,它们可能覆盖相当多的屏幕空间,所以我怀疑(没有确认)计时器到期并以相当高的速率重置以生成流畅的动画。由于您的动画需要很长时间,您可以修改 animate 函数,以便可以通过选项设置动画进行的速率。在您的情况下,您只需要每 250 毫秒左右更新一次,因为您大约每秒覆盖大约 3-4 个像素。

于 2009-01-19T21:43:14.200 回答
20

人们提到减慢 jQuery 的刷新率。您可以使用此文件 (jquery.animation-fix.js) 覆盖 jQuery 1.4 中的计时器功能:

function now() {
    return (new Date).getTime();
}
jQuery.fx.prototype.custom = function( from, to, unit ) {
    this.startTime = now();
    this.start = from;
    this.end = to;
    this.unit = unit || this.unit || "px";
    this.now = this.start;
    this.pos = this.state = 0;

    var self = this;
    function t( gotoEnd ) {
        return self.step(gotoEnd);
    }

    t.elem = this.elem;

    if ( t() && jQuery.timers.push(t) && !jQuery.fx.prototype.timerId ) {
        //timerId = setInterval(jQuery.fx.tick, 13);
        jQuery.fx.prototype.timerId = setInterval(jQuery.fx.tick, 2050);
    }
}

所以用这个修改行

jQuery.fx.prototype.timerId = setInterval(jQuery.fx.tick, 50);

将 50 更改为您想要的任何间隔。以毫秒 (ms) 为单位

如果将此代码保存在不同的文件中,则可以像这样附加它:

<script src="/js/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="/js/jquery.animation-fix.js" type="text/javascript"></script>
于 2010-05-23T22:01:30.723 回答
3

jQuery animate 使用 javascript 函数 'setInterval' 每隔几毫秒更新一次对象。不幸的是,jQuery 中的间隔默认为“13 毫秒”。那是每秒 76 次更新。对于这样的慢速和中等动画来说,要多得多了。

13ms 被硬编码到 jQuery 中。所以你只能在jQuery.js中直接改变这个值。如果你只有缓慢的 clowds,你可以达到 100 毫秒。如果你也有一些更快的动画,你应该把它设置为 50。

您可以更改 setInterval() 的参数;在自定义函数中。'jQuery.fx.prototype { ... custom: function() { ... } ... }'

于 2009-10-22T17:29:51.643 回答
2

动画涉及循环操作,无论如何这些都会真正消耗 CPU。

我不知道用 jQuery 做起来有多容易,但需要发生的是动画需要消耗更少的周期。要么你让 ani 更加锯齿(显示不那么流畅),循环需要优化,或者减少 ani 的工作。

40秒?动画是不是有点长?我认为他们应该比这更直接。

于 2009-01-19T21:44:03.950 回答
2

我刚刚在 Scriptaculous 下观察了动画的性能,发现了类似的 CPU 峰值:IE 大约为 50%,Firefox 的性能稍好(16-30%)——两者都在 DuoCore PC 上。由于 JQuery 和 Scriptaculous 都是通过更改底层 CSS 来工作的,所以我认为可以肯定地说任何 Javascript 实现在计算上都会很昂贵。

您很可能会被 Flash 卡住。

于 2009-01-19T21:47:00.917 回答
0

我真的很喜欢 Tim 发布的答案,尽管我需要让这个修复程序在 Drupal 6 生产环境中工作。

我通过使用 jQuery 更新模块安装了 jQuery 1.3.2,所以我使用的和 Tim 的修复程序设计的 jQuery 1.4 之间存在一些差异。

按照蒂姆的指示,我完成了 90% 的工作,我只需要花 10 分钟的时间来想出这段代码。

25 - 33 的计时器值似乎比 13 毫秒的中速动画效果好得多,例如褪色背景图像。

var timerId;

function now() {
    return (new Date).getTime();
}

jQuery.fx.prototype.custom = function( from, to, unit ) {
    this.startTime = now();
    this.start = from;
    this.end = to;
    this.unit = unit || this.unit || "px";
    this.now = this.start;
    this.pos = this.state = 0;

    var self = this;
    function t( gotoEnd ) {
        return self.step(gotoEnd);
    }

    t.elem = this.elem;

        if ( t() && jQuery.timers.push(t) && !timerId ) {
    timerId = setInterval(function(){
        var timers = jQuery.timers;

        for ( var i = 0; i < timers.length; i++ )
            if ( !timers[i]() )
                timers.splice(i--, 1);

        if ( !timers.length ) {
            clearInterval( timerId );
            timerId = undefined;
        }
    }, 25);
}
};
于 2010-08-16T00:04:40.663 回答