jQuery animate() и производительность браузера

У меня есть некоторые элементы, которые я перемещаю по странице очень медленно. По сути, я уменьшаю левое поле двух изображений в течение 40 секунд или около того.

Визуально работает красиво. Тем не менее, мой процессор загружается примерно на 50% во время анимации. Это также не относится к какому-либо отдельному браузеру — то же самое происходит в Safari3 и Firefox3. Если у меня оба браузера запускают страницу, мой процессор кричит при загрузке около 95%.

Я использую jQuery 1.3. Обе анимации происходят одновременно. На странице нет Flash. Если я закомментирую код (удалю анимацию) и обновлю страницу, мой процессор немедленно вернется к нормальному использованию.

Я надеюсь, что мне не придется прибегать к Flash, но даже просмотр шоу на Hulu.com не вызывает такого скачка моего процессора.

Мысли?


person Jeremy Ricketts    schedule 19.01.2009    source источник


Ответы (7)


Я думаю, что способ работы jQuery animate() заключается в том, что он использует таймер, который периодически срабатывает и вызывает функцию, которая обновляет DOM, чтобы отразить состояние анимации. Как правило, анимация относительно короткая и может занимать довольно много места на экране, поэтому я подозреваю (без подтверждения), что таймер истекает и сбрасывается с довольно высокой скоростью для создания плавной анимации. Поскольку ваша анимация занимает много времени, вы можете изменить функцию анимации, чтобы скорость, с которой происходит анимация, можно было установить с помощью параметра. В вашем случае вам нужно будет обновлять только каждые 250 мс или около того, поскольку вы покрываете примерно 3-4 пикселя в секунду.

person tvanfosson    schedule 19.01.2009
comment
Поскольку анимация уже медленная, мне интересно, не приведет ли это к тому, что анимация будет неровной. Пытаюсь избежать того, чтобы страница выглядела как старая игра Atari. хаха. Я не знаю, как вы думаете, Флэш был бы лучше подготовлен для этого? - person Jeremy Ricketts; 20.01.2009
comment
Нет. Вам придется заставить мигать всю страницу. IIRC, вы не можете использовать его в качестве фонового элемента - person StingyJack; 20.01.2009
comment
Этот бит будет в области заголовка сайта. Так что я думаю, что размещение флеш-ролика за основным контентом может быть вариантом. Хотя я ничего не знаю о самом создании Flash-ролика. Я много с ними работаю, но не пишу их. :-/ - person Jeremy Ricketts; 20.01.2009
comment
Принятие этого из-за подробного описания характера проблемы и предлагаемого обходного пути. Тем не менее спасибо всем! Первый вопрос Stackedoverflow имел бешеный успех. Я вернусь сюда, чтобы помочь другим тоже. - person Jeremy Ricketts; 20.01.2009
comment
Если вам это не нужно в качестве фона, тогда Flash — это вариант. - person StingyJack; 20.01.2009
comment
Есть идеи, как изменить частоту обновления анимации? - person Marcus Downing; 11.07.2009
comment
@Marcus - покопайтесь в jQuery и найдите, где установлен таймер. Отрегулируйте время до обработки следующего события в очереди анимации. - person tvanfosson; 12.07.2009

Я знаю, что это старый вопрос, и Тим дал отличный ответ, но я просто подумал, что должен опубликовать обновление для тех, кто ищет решение этой проблемы, так как теперь есть более простой способ...

Начиная с jQuery 1.4.3, вы можете установить интервал, который jQuery использует анимация, напрямую через jQuery.fx.interval. Итак, вы можете просто сделать что-то вроде:

jQuery.fx.interval = 50;
person Alconja    schedule 08.12.2010
comment
это устанавливает глобальный интервал для всех анимаций. Вы случайно не знаете, как можно установить интервал только для одной конкретной анимации? - person Hans; 05.06.2012
comment
@Marcel - Не то, чтобы я знал, я считаю, что все анимации имеют один и тот же внутренний таймер, но я могу ошибаться ... - person Alconja; 05.06.2012
comment
24 кадра в секунду, скорость, с которой ведется большая часть съемок, кажется хорошей отправной точкой для игры с этим числом. Итак, 1000 мс / 24 кадра в секунду = ~ 42 - person Matt Parkins; 12.11.2012
comment
По умолчанию 13 (миллисекунды) - person bendytree; 23.04.2013

Люди упоминали о замедлении частоты обновления jQuery. Вы можете переопределить функцию таймера в jQuery 1.4 с помощью этого файла (jquery.animation-fix.js):

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 на любой интервал, который вы хотите. То есть в миллисекундах (мс)

Если вы сохраните этот код в другом файле, вы можете прикрепить его следующим образом:

<script src="/js/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="/js/jquery.animation-fix.js" type="text/javascript"></script>
person Tim    schedule 23.05.2010
comment
Я просто подумал, интересно, вы могли бы включить это в плагин, который устанавливает setInterval для каждой анимации. Например, вы можете добавить параметр на api.jquery.com/animate, который изменяет интервал для этого пункт. Хм. - person Jeremy Ricketts; 13.06.2010
comment
Тим, это именно то, что я искал! Мне нравится твоя работа :) - person David Meister; 28.08.2010
comment
Примечание для всех, кто использует это решение: эта функция теперь встроен в jQuery, начиная с версии 1.4.3. (+1 за отличное решение для версии до 1.4.3). - person Alconja; 09.12.2010

jQuery Animate использует функцию javascript setInterval для обновления объектов каждые несколько миллисекунд. К сожалению, интервал в jQuery по умолчанию составляет «13 мс». Это 76 обновлений каждую секунду. Слишком много для таких медленных и средних анимаций.

13 мс жестко закодированы в jQuery. Таким образом, вы можете напрямую изменить это значение только в jQuery.js. Если у вас есть только медленные облака, вы можете увеличить время до 100 мс. Если у вас также есть несколько более быстрых анимаций, вы должны установить его на 50.

Вы можете изменить параметр для setInterval(); в функции custom. 'jQuery.fx.prototype {... custom: function() {... }...}'

person Alexander von Weiss    schedule 22.10.2009
comment
Чувак, это был бы убойный jQuery-плагин. Что-то, что добавляет параметр интервала в animate(). - person Jeremy Ricketts; 24.10.2009

Анимации включают в себя циклические операции, и они действительно будут нагружать процессор, несмотря ни на что.

Я не знаю, насколько легко это сделать с помощью jQuery, но что должно произойти, так это то, что анимация должна потреблять меньше циклов. Либо вы делаете ани немного более неровным (отображение не такое гладкое), либо нужно оптимизировать зацикливание, либо уменьшать работу ани.

40 секунд? не слишком ли это длинно для анимации? Я думал, что они должны быть немного более непосредственными, чем это.

person StingyJack    schedule 19.01.2009
comment
Анимация представляет собой тонкое движение облаков в верхней части страницы. Они начинаются в случайном месте и медленно двигаются влево. - person Jeremy Ricketts; 20.01.2009

Я только что наблюдал за производительностью анимации в Scriptaculous и обнаружил схожие всплески ЦП: примерно 50% для IE, чуть более высокую производительность (16-30%) для Firefox — оба на ПК с DuoCore. Поскольку и JQuery, и Scriptaculous работают, изменяя лежащий в их основе CSS, я думаю, можно с уверенностью сказать, что любая реализация Javascript требует больших вычислительных ресурсов.

Вы вполне можете застрять с Flash.

person rtperson    schedule 19.01.2009

Мне очень нравится ответ, опубликованный Тимом, хотя мне нужно было, чтобы это исправление работало в производственной среде Drupal 6.

У меня установлен jQuery 1.3.2 благодаря использованию модуля обновления jQuery, поэтому есть несколько различий между тем, что я использую, и 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);
}
};
person David Meister    schedule 16.08.2010