#javascript #jquery #animation #loops
#javascript #jquery ( jquery ) #Анимация #петли
Вопрос:
Я попытался написать свою собственную анимационную функцию, чтобы анимировать подсчет вверх и вниз числа, используя циклы и 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 ) amp;amp; 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';
}
}
Комментарии:
1. Широкий, но очень интересный вопрос. ( 1)
2. Я бы сказал, что вы должны видеть примерно одинаковую производительность в каждом из этих браузеров для простых анимаций (если я чего-то не упускаю). Не могли бы вы показать нам свой код?
3. setInterval не обязательно должен срабатывать, когда вы ему прикажете, хотя он старается изо всех сил. Я считаю, что jQuery использует процентную базу текущего времени
4. Отредактировано для добавления кода
Ответ №1:
Я не вижу ничего в вашем коде, проверяющем разницу во времени. В большинстве библиотек (jQuery, MooTools и т. Д.) Анимация настраивается в зависимости от времени.
jQuery использует метод step
, который используется для определения следующего значения эффекта. Чтобы посмотреть на эту функцию, откройте разработанную (несжатую) версию jQuery и выполните поиск jQuery.fx.prototype
. Этот блок кода содержит step
метод.
Допустим, вы хотите указать элементу перейти из одной позиции в другую. Похоже, что ваш код будет повторяться до тех пор, пока не будет завершено фиксированное количество анимаций. Таким образом, вы строго относитесь к количеству итераций, а не ко времени. Браузеры часто лагают. Кто-то может запускать на своей машине всевозможный мусор, что замедлит вашу работу. И тогда общее выполнение вашей анимации будет дольше, чем предполагалось, а сама анимация будет «отрывистой».
Итак, что вам следует сделать вместо этого, так это быть строгим во времени и не пытаться применять равномерные шаги. Каждый раз, когда вы «шагаете» по анимации, вы должны учитывать время начала анимации, общее время, необходимое для завершения анимации, и сколько времени прошло. С его помощью вы можете определить, где должна быть анимация. Итак, если вы хотите переместить элемент (линейно) из позиции 100 в позицию 200 за 10 секунд, а у нас 7,5 секунды, вы знаете, что позиция должна быть 175. Затем, как только время достигнет или превысит завершенные 10 секунд, вы устанавливаете его на 200 и прерываете цикл.
Код jQuery будет немного сложно прочитать из-за используемых им эффектов смягчения, а также всех внутренних перехватов и обратных вызовов. Но идея довольно прямолинейна.
Комментарии:
1. Итак, позиция анимации является компонентом ее времени, когда она снова повторяется в цикле. В этом больше смысла. Я постараюсь переписать это заново. Спасибо!
Ответ №2:
Ответ Маршалла работает там, где вы хотите, чтобы анимация выполнялась в течение определенного промежутка времени. Еще одно требование заключается в том, чтобы что-то запускалось в точное время, например, по тиканью часов. Для этого вы используете setTimeout и при каждом запуске функции вычисляете время до следующего «тика» и вызываете setTimeout с этим интервалом (или немного более длинным интервалом в случае часов, чтобы убедиться, что следующее обновление происходит сразу после следующего целого тика).
Используя последовательные вызовы setTimeout, вы можете компенсировать смещение, связанное с setInterval .