2015-07-03 2 views
0

Я пытаюсь понять одну вещь о requestAnimationFrame.requestAnimationFrame Fixed Duration

В приведенном ниже примере кода я запускаю что-то 60 раз, которое должно соответствовать типичным 60 кадрам в секунду, которое вы обычно получаете, поэтому оно должно длиться 1 секунду. Однако я намеренно вытащил его, вызвав функцию траты времени.

Очевидно, это занимает больше времени (около 5 секунд на моей машине).

Вопрос в том, как мне настроить анимацию так, чтобы она длилась фиксированной продолжительностью, такой как 1 секунда - предположительно это должно пропускать несколько кадров в процессе?

Хотя пример звучит специфично, он имеет более широкий контекст. Я хотел бы создавать анимации, такие как затухание или скольжение, которые имеют заданную продолжительность, а не определенное количество кадров, поскольку частота кадров не является полностью предсказуемой. Это будет соответствовать поведению анимации CSS3.

Благодаря

var i=0; 
 
var start=new Date(); 
 
var end; 
 

 
var counter=document.getElementById('counter'); 
 
var time=document.getElementById('time'); 
 

 
doit(); 
 

 
function doit() { 
 
    if(i>=60) { 
 
    end=new Date(); 
 
    time.innerHTML=end.getTime() - start.getTime(); 
 
    return; 
 
    } 
 
    wasteTime(); 
 
    counter.innerHTML+=i+' '; 
 
    i++; 
 
    requestAnimationFrame(doit) 
 
} 
 

 
function wasteTime() { 
 
    for(var i=0;i<100000000;i++); 
 
}
<p id="counter"></p> 
 
<p id="time"></p>

+0

Использование 'setInterval' Вместо с собственным временем. –

ответ

0

Если вместо этого вы хотите использовать фиксированный интервал между вашими петлями, вы лучше использовать setInterval();

var myInterval = setInterval(doit,1000); 

Это будет инициировать DoIt() - каждую секунду. Для того, чтобы отменить интервал вы

clearInterval(myInterval); 

Если вы все еще хотите использовать преимущества использования requestAnimationFrame, вы можете комбинировать его с setInterval

var myInterval = setInterval(function() { 
    requestAnimationFrame(doit); 
},1000); 

Хотя я не уверен, как выше будет играть если вы посещаете другую вкладку, и функция setInterval начнет выравнивать все эти rAF, так что имейте в виду.

+0

За исключением 'cancelInterval', который должен быть' clearInterval'. Этот ответ правильный! @ down-voter –

+0

@VinodKumar да, хорошо поймать – Niddro

+0

Добро пожаловать :) –

1

setInterval это неправильное решение.

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

В вашем примере случае, вам нужно, чтобы увеличить i рядом, соответствующим количеством времени, прошедшего с момента последнего кадра:

var i=0; 
 
var start=new Date(); 
 
var last=new Date(); 
 
var end; 
 

 
var counter=document.getElementById('counter'); 
 
var time=document.getElementById('time'); 
 

 
doit(); 
 

 
function doit() { 
 
    if(i>=60) { 
 
    end=new Date(); 
 
    time.innerHTML=end.getTime() - start.getTime(); 
 
    return; 
 
    } 
 
    
 
    //Rather than just incrementing i by 1, here we 
 
    //look at the difference since the last frame 
 
    //and increment i by an appropriate amount 
 
    var diff = new Date() - last; 
 

 
    counter.innerHTML+=i+' '; 
 
    i += diff/60; 
 

 
    requestAnimationFrame(doit) 
 
    last = new Date(); 
 
    wasteTime(); 
 
} 
 

 
function wasteTime() { 
 
    for(var i=0;i<100000000;i++); 
 
}
<p id="counter"></p> 
 
<p id="time"></p>

Примечание: Я не уверен почему это все еще занимает больше 1 секунды, чтобы работать, все еще глядя. Возможно, он взаимодействует с браузером, чтобы выписать HTML.

+0

Если запрошенное время меньше, чем frameRate, оно замедляется и вызывает проблему с рендерингом. Но он просто хочет отдать каждую секунду, а это достаточно времени. Я не вижу проблем с использованием 'setInterval'. –

+0

Нет, он хочет, чтобы он длился всего 1 секунду. –

+0

О! Я думаю, вы правы. Извините, я неправильно понял. –

0

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

Счетчик в примере ниже не должен увеличиваться, а устанавливается пропорционально. Если это так, его также можно правильно использовать для выхода.

Другой трюк заключается в использовании параметра временной метки обратного вызова.

Спасибо!

/* \t HTML 
 
\t ================================================ 
 
\t <p id="counter"></p> 
 
\t <p id="time"></p> 
 
\t ================================================ */ 
 

 

 
var limit=60; 
 
var i=0; 
 
var start=null; 
 

 
var counter=document.getElementById('counter'); 
 
var time=document.getElementById('time'); 
 

 

 
doit(); 
 

 
function doit(timestamp) { 
 
\t if(!start) start=timestamp; 
 
\t var lapsed=timestamp-start; 
 
\t if(lapsed>=1000) { \t // \t if(i>=limit) { 
 
\t \t time.innerHTML='<br>'+lapsed; 
 
\t \t return; 
 
\t } 
 
\t wasteTime(); 
 
\t counter.innerHTML += i+' '; 
 
\t i=lapsed/1000*limit; \t \t // \t Rather than increment 
 
\t requestAnimationFrame(doit) 
 
} 
 

 
function wasteTime() { 
 
\t for(var i=0;i<100000000;i++); 
 
}
<p id="counter"></p> 
 
<p id="time"></p>