jQuery animate () и производительность браузера - PullRequest
35 голосов
/ 20 января 2009

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

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

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

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

Мысли

Ответы [ 7 ]

44 голосов
/ 09 декабря 2010

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

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

jQuery.fx.interval = 50;
34 голосов
/ 20 января 2009

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

20 голосов
/ 24 мая 2010

Люди упоминают о снижении частоты обновления 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>
3 голосов
/ 22 октября 2009

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

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

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

2 голосов
/ 20 января 2009

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

Возможно, вы застряли с Flash.

2 голосов
/ 20 января 2009

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

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

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

0 голосов
/ 16 августа 2010

Мне очень нравится ответ, опубликованный Тимом, хотя мне нужно было, чтобы это исправление работало в производственной среде 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);
}
};
...