Как jquery последовательно выполняет анимационные функции за (почти) точное время? - PullRequest
6 голосов
/ 21 октября 2011

Я попытался написать свою собственную функцию анимации для анимации подсчета числа вверх и вниз с помощью циклов и функции setInterval.В Chrome он, кажется, работает очень хорошо, но в Firefox он кажется запаздывающим и занимает гораздо больше времени, чем предписанное время завершения.

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

Редактировать:Вот мой код, так как он был запрошен:

function tallyPrices(){

var current_total = parseFloat( $('.budget span').text() );
var new_total = 0;  
var animation_options = {
    iterationTime : 10,
    totalTime : 500
}

$('#chosen-items li').each( function(){
    if( $(this).attr('data_price') !== 'n/a' ){
        new_total += parseFloat( $(this).attr('data_price') );
    }
});

animation_options.difference = current_total - new_total;
animation_options.delta = Math.round( Math.abs( animation_options.difference / ( animation_options.totalTime / animation_options.iterationTime ) ) * 100 ) / 100;

var timesIterated = 0;
var limit = parseFloat( $('.budget span').attr('data_high') );

var animation = setInterval( function(){
    timesIterated = priceAnimate( timesIterated, animation_options, $('.budget span'), limit);

    if(timesIterated === 'done'){
        clearInterval(animation);
        $('.budget span').text( parseFloat( Math.round( new_total * 100 ) / 100 ).toFixed(2) );
    }
}, animation_options.iterationTime );
}

function priceAnimate( count, options, el, limit ){
if( count < ( options.totalTime / options.iterationTime ) && options.difference !== 0){
    var current = parseFloat( el.text() );
    current = Math.round( current * 100 ) / 100;

    if( options.difference < 0 ){
        el.text( parseFloat( Math.round( (current + options.delta) * 100 ) / 100 ).toFixed(2) );
    } else if( options.difference > 0 ){
        el.text( parseFloat( Math.round( (current - options.delta) * 100 ) / 100 ).toFixed(2) );
    }

    if( parseFloat( el.text() ) > limit ){
        el.parent().addClass('over');
    } else {
        el.parent().removeClass('over');
    }

    count++;

    return count; 
} else {
    return 'done';
}
}

Ответы [ 2 ]

2 голосов
/ 21 октября 2011

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

jQuery использует метод step, который используется для определения следующего значения для эффекта.Чтобы посмотреть на эту функцию, откройте версию jQuery для разработчиков (без сжатия) и найдите jQuery.fx.prototype.Этот блок кода содержит метод step.

Допустим, вы хотите указать элементу перемещаться из одной позиции в другую.Похоже, ваш код будет повторяться, пока не будет завершено с фиксированным количеством анимаций.Таким образом, вы строго по количеству итераций, а не по времени.Браузеры часто отстают.Кто-то может запускать на своем компьютере всякие ненужные файлы, что замедлит ваше выполнение.И тогда общее выполнение вашей анимации будет дольше, чем предполагалось, и сама анимация будет «отрывочной».

Итак, вместо этого вы должны быть строгими со временем и не пытаться выполнять даже шаги.Каждый раз, когда вы «шагаете» по анимации, вы должны учитывать время начала анимации, общее время, необходимое для завершения анимации, и сколько времени прошло.При этом вы можете сказать, где анимация должна быть.Поэтому, если вы хотите переместить элемент (линейно) из позиции 100 в 200 за 10 секунд, а у нас есть 7,5 секунды, вы знаете, что позиция должна быть 175. Затем, как только время достигнет или превысит 10 секунд, вы устанавливаетедо 200 и уничтожить цикл.

Код jQuery будет немного трудно прочитать из-за эффектов замедления, которые он использует, и всех внутренних хуков и обратных вызовов.Но идея довольно проста.

1 голос
/ 21 октября 2011

Ответ Маршалла работает там, где вы хотите, чтобы анимация запускалась через определенное время.Другое требование - запускать что-то в определенное время, например, тик.Для этого вы используете setTimeout и при каждом запуске функции рассчитывает количество времени до следующего «тика» и вызываете setTimeout с этим интервалом (или немного более длинным интервалом вслучай часов, чтобы удостовериться, что следующее обновление будет сразу после следующего целого тика).

Используя последовательные вызовы setTimeout , вы можете компенсировать дрейф, связанный с setInterval .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...